<?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: Travis CI</title>
    <description>The latest articles on DEV Community by Travis CI (@travisci).</description>
    <link>https://dev.to/travisci</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%2F3141%2F8940e5ae-eb9e-4b20-9b60-b618e34c4047.png</url>
      <title>DEV Community: Travis CI</title>
      <link>https://dev.to/travisci</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/travisci"/>
    <language>en</language>
    <item>
      <title>Travis CI Pipelines: 2 Approaches to Source Control Branching</title>
      <dc:creator>Montana Mendy</dc:creator>
      <pubDate>Wed, 17 Feb 2021 13:22:23 +0000</pubDate>
      <link>https://dev.to/travisci/travis-ci-pipelines-2-approaches-to-source-control-branching-49d2</link>
      <guid>https://dev.to/travisci/travis-ci-pipelines-2-approaches-to-source-control-branching-49d2</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fHVIhpdB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ei48t0tm808v3q0zyai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fHVIhpdB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ei48t0tm808v3q0zyai.png" alt="Alt Text" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feature branching is a game-changing aspect of modern software development. Being able to have a developer implement a new feature in a body of code in a safe, independent, isolated manner using Git branching is an overall positive approach to the way companies make software.&lt;/p&gt;

&lt;p&gt;Over the years, two techniques of feature branching have emerged. One is what I call &lt;em&gt;branching from repo&lt;/em&gt;. The other is &lt;em&gt;branching from fork&lt;/em&gt;. Let’s explore each technique, as well as their benefits and tradeoffs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Branching from repo
&lt;/h2&gt;

&lt;p&gt;Branching from repo is a pattern in which feature branches are created off an existing branch in a business’s repository and then assigned to or assumed by a particular developer for implementation. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r8T6lEl---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jtqhvq3vbdgo53y5riit.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r8T6lEl---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jtqhvq3vbdgo53y5riit.png" alt="Alt Text" width="703" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Figure 1: The branching from repo pattern is used to implement feature branches created from a particular branch in a business’s repository.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The branching from repo pattern is confined to creating feature branches that are within the boundaries of a particular business’s repository. Thus, only personnel or services that have the proper permissions for working that repository can create a particular feature branch. &lt;/p&gt;

&lt;p&gt;The important thing to understand about branching from repo is that all the work that goes with creating the feature branch, developing the feature’s code, and then issuing the pull request for the completed code is done from within the boundary of the given repository. Those people on the “outside” have no ability to contribute changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Branching from fork
&lt;/h2&gt;

&lt;p&gt;In the branching from fork pattern, a developer interested in adding to and improving upon code in a given repository forks the code into their own repository. Then, the developer creates branches against the forked code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nmdtVqc8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zl3l7fmor9gzbv8j44o1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nmdtVqc8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zl3l7fmor9gzbv8j44o1.png" alt="Alt Text" width="880" height="575"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Figure 2: Developers use the branching from fork pattern to fork code from the business’s repository into the developer’s external repository to then create a feature branch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once work on a given branch is complete, the developer makes a pull request to merge the code back into the originating repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--03kCAhz4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2j79olt1ala6owgkspi4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--03kCAhz4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2j79olt1ala6owgkspi4.jpg" alt="Alt Text" width="880" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Figure 3: GitHub supports pull requests for merging code between repositories in separate accounts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The important thing to understand about the branching from fork pattern is that it allows any developer to make improvements to code in an external repository in a controlled manner. All that’s required is view access to a repository of interest and then the cloning of the code.&lt;/p&gt;

&lt;p&gt;Once the code is cloned, the developer is free to work on improvements according to their own software development process. The original repository is independent of the forked code; the only intersection between the two is when the pull request is made from the forked repository back to the originating repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages and tradeoffs
&lt;/h2&gt;

&lt;p&gt;Both patterns have advantages and trade-offs. Let’s examine them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Branching from repo is well suited to private governance
&lt;/h3&gt;

&lt;p&gt;Branching from repo is well suited for companies that want to keep their software development process private and subject only to their own development and project management practices.&lt;/p&gt;

&lt;p&gt;Typically, a feature branch is created to accommodate a request that exists in a company’s backlog of work. In some cases, a feature branch can be created ad hoc, but usually, they are created by a governing authority within the company, such as a project manager or tech lead. Either the feature branch is created directly or as an ancillary action taken by automation within a project management platform such as Jira. As such, branching from repo allows project managers and tech leads to exert a lot of control over who can work on code. Also, the governing authority can determine the status of the feature branch by viewing the code as well as the branch’s commit history.&lt;/p&gt;

&lt;p&gt;The trade-off is that branching from repo requires that those working on the code have a known relationship to the repository from within the source control management service hosting the code. For example, if the code is hosted on GitHub, a developer must have permission to make commits to the feature branch. Typically, this means inviting the developer to be a direct contributor to the repository or a member of an organization associated with the project. While this degree of formality provides control, it also excludes the general public from working on the code in an ad hoc manner, so there is less opportunity to benefit from the informal interest of others. Fortunately, branching from fork addresses this shortcoming.&lt;/p&gt;

&lt;h3&gt;
  
  
  Branching from fork is well suited to open-source development
&lt;/h3&gt;

&lt;p&gt;Branching from fork is well suited for volunteer-based open-source development. Branching from repo is pretty much a “We’re assigning you some code to work” approach. On the other hand, branching from fork says, “Here’s some code. Feel free to work on it, but you need to figure out what you want to work on to make it better.”&lt;/p&gt;

&lt;p&gt;In order for a developer to improve code using branching from fork, they need to identify possible improvements. This can take many forms. For instance, a developer can find problems to solve by going over the list of open issues in the source control management service that’s hosting the code. Once an issue is identified, the developer can address it according to their own development style and timeframe.&lt;/p&gt;

&lt;p&gt;In addition to addressing known issues, a developer can implement, in an unsolicited manner, a feature they would like to see in the code. There’s no need to ask for permission. All that needs to be done is to implement the feature and then submit a pull request back to the original project. At that point, it’s up to the project’s maintainers to use the improvement. If the unsolicited feature is not accepted, it still exists in the fork and is available to interested parties there.&lt;/p&gt;

&lt;p&gt;One drawback of branching by fork is that making contributions can require a good deal of work. Regardless of whether the developer is working on a known issue, implementing an existing feature request, or offering an unsolicited improvement, they will still need to learn the code. That learning curve can be significant, particularly if the developer has limited access to others who are willing to help. Sometimes the help required to fill in the gaps might be available, but many times it’s not. If the documentation is poor or the code is cryptic, figuring out how to make a meaningful improvement can take a lot of time. As those who have worked with volunteers can attest, the best volunteer experience is the one that’s the easiest. The more difficult the undertaking, the greater the risk of losing the volunteer’s sense of investment.&lt;/p&gt;

&lt;p&gt;Conversely, a developer working on a feature request according to the branching from repo pattern will usually be a member of the business or organization that owns the repository. Thus, they will usually enjoy the support of other members who have experience working with the code. There’s both formal and tribal knowledge that’s available, so things are easier.&lt;/p&gt;

&lt;p&gt;Another drawback of branching from fork is that since anybody can make a contribution, anybody will. This means that the code submitted via a pull request will vary in quality: Some of it will be quite good, but some of it will be quite bad. This creates more work for those who actually have to review pull requests in order to make sure that a submission meets quality standards. While a certain degree of quality control can be accomplished using automation, there are still aspects of the pull request that will require human inspection, particularly if the code is complex.&lt;/p&gt;

&lt;p&gt;In short, branching from fork allows more people to work on code in their own manner, but making meaningful contributions is harder for all parties involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;The beauty of being able to branch source code is that it allows developers to work on code in a safe, controllable manner. Modern software development depends on branching.&lt;/p&gt;

&lt;p&gt;The beauty of forking is that it provides a way for independent parties to work on an entire repository hosted in a source control management platform, such as GitHub or BitBucket, in an independent manner without affecting the original repository. Combining branching and forking creates a new dimension in software development.&lt;/p&gt;

&lt;p&gt;Whether you use the branching from repo technique or the branching from fork technique, the important thing is that both methods provide developers a significant degree of independence while ensuring that the code that eventually makes its way into production will be the highest quality possible.&lt;/p&gt;

</description>
      <category>news</category>
      <category>feature</category>
      <category>infrastructure</category>
      <category>community</category>
    </item>
    <item>
      <title>Configuring Travis CI to Run a Deno Project</title>
      <dc:creator>Montana Mendy</dc:creator>
      <pubDate>Wed, 17 Feb 2021 12:52:42 +0000</pubDate>
      <link>https://dev.to/travisci/the-cookbook-build-matrix-46ip</link>
      <guid>https://dev.to/travisci/the-cookbook-build-matrix-46ip</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jSZztBxE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ugqcvjknxpcn04bvegp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jSZztBxE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ugqcvjknxpcn04bvegp.png" alt="Alt Text" width="880" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nothing lasts forever in the world of ephemeral computing. It’s the nature of the beast. Today, more companies are maximizing their IT budgets by practicing the principles of infrastructure as code (IaC). They’re creating and destroying virtual assets on demand in order to meet the needs of the moment. &lt;/p&gt;

&lt;h1&gt;
  
  
  Getting started
&lt;/h1&gt;

&lt;p&gt;I am a big fan of Deno. I am also a big fan of Travis CI. What’s not to like? Deno is a powerful new programming framework that picks up where Node.js left off. Travis CI is a CI/CD platform that integrates easily with the projects stored in my GitHub repo. They’re both very cool.&lt;/p&gt;

&lt;p&gt;But there’s a problem: Travis CI does not support Deno out of the box. Let's see what we can do.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://deno.land"&gt;Deno&lt;/a&gt; is still in its infancy, so it makes sense that it is not quite yet on the Travis CI radar. Still, no biggie. Travis CI is flexible enough to allow me to build support for Deno right into the CI/CD workflow that kicks off when my Deno project runs on Travis CI. In fact, getting Deno to run on Travis CI was pretty easy, and the results are very useful, so allow me to share.&lt;/p&gt;

&lt;p&gt;First I’m going to cover the overall process for deploying to Travis CI and running a workflow defined in a &lt;code&gt;.travis.yml&lt;/code&gt; file. Then I’ll show you the custom &lt;code&gt;.travis.yml&lt;/code&gt; file I wrote that has Travis CI install Deno and run the unit tests for my Deno project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Travis CI 101
&lt;/h2&gt;

&lt;p&gt;Travis CI runs a CI/CD process right out of the box as part of its signup process. The first time you come to travic-ci.org, you’ll be asked to log in to Travis CI using your GitHub or BitBucket credentials. (The Bitbucket signup is in beta.)&lt;/p&gt;

&lt;p&gt;The signup process asks you to declare repositories on the source code management (SCM) service, into which a webhook will be installed. Once a webhook is installed on the given repository, Travis CI will receive notifications about events that happen in that repository. For example, when a developer commits code into a repository that has a webhook installed, Travis CI will be notified about the commit.&lt;/p&gt;

&lt;p&gt;Travis CI will clone the contents of that repo into a virtual machine instance running in the Travis CI domain. Once the runner VM has the contents of the cloned repository, it will look for a special file named travis.yml that contains instructions for provisioning the VM and about tasks to perform once the runner VM is provisioned. Figure 1 below describes the process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nxwqTdg---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5jmyrqju3qw7b5jauabm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nxwqTdg---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5jmyrqju3qw7b5jauabm.png" alt="Alt Text" width="880" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Figure 1: The Travis CI Workflow&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you can see in callout 1 above, the first step in the workflow process is that a developer commits updated code to the repository of interest in the SCM service running in the cloud. A webhook in the repository “sees” the commit and emits an event message that is captured by Travis CI, as shown at callout 2. Travis CI clones the repository’s code into a VM in its domain and then looks for the &lt;code&gt;.travis.yml&lt;/code&gt; file in the cloned files. The &lt;code&gt;.travis.yml&lt;/code&gt; file is identified, and the configuration and instructions in &lt;code&gt;.travis.yml&lt;/code&gt; are executed, as shown at callout 3.&lt;/p&gt;

&lt;p&gt;The process is straightforward, and it’s quite powerful in that we can construct the &lt;code&gt;.travis.yml&lt;/code&gt; file to define custom configuration and execute tasks that are special, too. In fact, we’re going to use &lt;code&gt;travis.yml&lt;/code&gt; to install the Deno language on the runner VM and then execute the unit tests that are part of my Deno project. This is very cool because, remember, as of this writing Travis CI does not support Deno out of the box.&lt;/p&gt;

&lt;p&gt;Let’s take a look at how support for Deno is implemented.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Travis CI to support Deno
&lt;/h2&gt;

&lt;p&gt;As mentioned above, the way you get Travis CI to do what you want it to do in its CI/CD process is to construct a &lt;code&gt;.travis.yml&lt;/code&gt; file according to the format defined in the Travis CI build config specification.&lt;/p&gt;

&lt;p&gt;The way I got Travis CI to support Deno was to do a bit of a hack in my project’s &lt;code&gt;.travis.yml&lt;/code&gt; file. The entire contents of &lt;code&gt;.travis.yml&lt;/code&gt; are shown below in listing 1. Let’s take a look at the details on a line-by-line basis:&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;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
&lt;span class="na"&gt;os&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker&lt;/span&gt;
&lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
&lt;span class="na"&gt;before_install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pwd&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl -fsSL https://deno.land/x/install/install.sh | sh&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ls -l $HOME/.deno&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export DENO_INSTALL="$HOME/.deno"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export PATH="$DENO_INSTALL/bin:$PATH"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deno run https://deno.land/std/examples/welcome.ts&lt;/span&gt;   
&lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cd ./simplecalc/test/&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sh run_test.sh&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cd ../../fortune_cookies/test&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sh run_test.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Listing 1: .travis.yml &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Travis CI allows you to define a &lt;a href="https://config.travis-ci.com/ref/language"&gt;language&lt;/a&gt; that gets implemented in the VM runner. It supports a &lt;a href="https://docs.travis-ci.com/user/languages/"&gt;variety of languages&lt;/a&gt; out of the box, but sadly, Deno isn’t one of them. Thus, at Line 1 in the travis.yml file above, I set the value of the &lt;code&gt;language&lt;/code&gt; attribute to &lt;code&gt;default&lt;/code&gt;. It really doesn’t matter which &lt;code&gt;language&lt;/code&gt; I define, because I am going to install Deno anyway.&lt;/p&gt;

&lt;p&gt;At line 2 at the os attribute, I set the runner VM’s operating system to Ubuntu. Travis CI supports the macOS and Windows operating system too, but I use Ubuntu because my code is intended to run on Linux.&lt;/p&gt;

&lt;p&gt;Travis CI allows you to configure the runner VM with a variety of services. For example, I could apply values to the services attribute that will install MySQL, Redis and Memcached to the runner VM automatically. In my case, I need to have Docker installed because one of my unit tests requires that a web server programmed under Deno be up and running as a Docker container. So at Lines 3 and 4, I set docker as a service.&lt;/p&gt;

&lt;p&gt;At line 2 at the &lt;a href="https://config.travis-ci.com/ref/os"&gt;os&lt;/a&gt; attribute, I set the runner VM’s operating system to Ubuntu. Travis CI supports the macOS and Windows operating system too, but I use Ubuntu because my code is intended to run on Linux.&lt;/p&gt;

&lt;p&gt;Travis CI allows you to configure the runner VM with a variety of &lt;a href="https://config.travis-ci.com/ref/job/services"&gt;services&lt;/a&gt;. For example, I could apply values to the services attribute that will install &lt;a href="https://www.mysql.com/"&gt;MySQL&lt;/a&gt;, &lt;a href="https://redislabs.com/"&gt;Redis&lt;/a&gt; and &lt;a href="https://www.memcached.org/"&gt;Memcached&lt;/a&gt; to the runner VM automatically. In my case, I need to have &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt; installed because one of my unit tests requires that a web server programmed under Deno be up and running as a Docker container. So at Lines 3 and 4, I set Docker as a service.&lt;/p&gt;

&lt;p&gt;Lines 5 through 7 set the &lt;a href="https://config.travis-ci.com/ref/job/branches"&gt;branches&lt;/a&gt; attribute to tell Travis CI to use the code in the master branch of the cloned repository. You can set Travis CI to process specific branches in a given repo, but in this case, the code I’m interested in unit testing is in the master branch.&lt;/p&gt;

&lt;p&gt;Lines 8 through 14 are where Deno support is implemented. I add the command line tasks required to download Deno. Once downloaded, the task will install Deno and then check that Deno is running. This is all defined under the &lt;code&gt;before_install&lt;/code&gt; attribute, which indicates the stage before installation in the &lt;a href="https://docs.travis-ci.com/user/job-lifecycle"&gt;Travis CI job lifecycle&lt;/a&gt;. The install stage is the time when all dependencies are installed, so in this case, I am telling Travis CI to install Deno before any other download and configuration happens.&lt;/p&gt;

&lt;p&gt;Line 9 tells Travis CI to output the present working directory &lt;a href="https://en.wikipedia.org/wiki/Pwd"&gt;(pwd)&lt;/a&gt;. I do this to provide debugging information that might be useful later.&lt;/p&gt;

&lt;p&gt;Line 10 runs the &lt;code&gt;curl&lt;/code&gt; command that downloads and executes the shell (sh) script that does the actual work of installing Deno.&lt;/p&gt;

&lt;p&gt;Line 11 lists the contents of the .deno directory. I do this to provide debugging information. When the Deno installation is run, it creates a .deno directory in the user’s &lt;code&gt;$HOME&lt;/code&gt; directory where the Deno binaries and dependencies are stored.&lt;/p&gt;

&lt;p&gt;Line 12 creates an environment variable, &lt;code&gt;DENO_INSTALL&lt;/code&gt; which describes the location of the Deno binary and dependencies.&lt;/p&gt;

&lt;p&gt;Line 14 runs the simple “Hello World” Deno application, which is downloaded directly from the Deno home site. I do this just to confirm that Deno is up and running properly.&lt;/p&gt;

&lt;p&gt;Lines 15 through19 run the unit tests for the various subjects that are part of my main projects. (See figure 2, below.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7nP2d8ul--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x0yy6wub4j71xn3zggpy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7nP2d8ul--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x0yy6wub4j71xn3zggpy.png" alt="Alt Text" width="880" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Figure 2: An excerpt from the console output created with travis.yml running my project’s unit tests&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s it. As you can see, I got Deno up and running under Travis CI using a trivial amount of code in the &lt;code&gt;.travis.yml&lt;/code&gt; file. Being able to do so much with such a small amount of code attests to the power that Travis CI brings to the CI/CD experience.&lt;/p&gt;

&lt;p&gt;You can view the code for this Deno project on GitHub &lt;a href="https://github.com/reselbob/denodemo"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join the initiative
&lt;/h2&gt;

&lt;p&gt;Travis CI provides the power and flexibility to make just about any CI/CD workflow possible. The platform’s versatility is reason enough for enterprises to consider adopting it. But when it comes to running Deno under Travis CI, there’s more!&lt;/p&gt;

&lt;p&gt;Travis CI supports implementing &lt;a href="https://docs.travis-ci.com/user/languages/community-supported-languages"&gt;community-based languages&lt;/a&gt;. Thus, it’s entirely possible to get Deno incorporated into the array of languages that Travis CI supports once the &lt;a href="https://docs.travis-ci.com/user/languages/community-supported-languages#adding-a-new-language"&gt;infrastructure&lt;/a&gt; is in place. All that’s required is for three members of the Deno community to commit to becoming maintainers and keeping the language support active. That being said, I am actively looking for people who want to become maintainers. &lt;/p&gt;

&lt;p&gt;Making Deno work out of the box with Travis CI is a win-win for all parties. If you’re interested, &lt;a href="https://www.linkedin.com/in/bobreselman"&gt;contact me on LinkedIn&lt;/a&gt;. It will be a great adventure, and the result of our endeavor will benefit many for years to come.&lt;/p&gt;

</description>
      <category>news</category>
      <category>feature</category>
      <category>infrastructure</category>
      <category>community</category>
    </item>
    <item>
      <title>The Cookbook: Build Matrix</title>
      <dc:creator>Montana Mendy</dc:creator>
      <pubDate>Thu, 11 Feb 2021 10:53:30 +0000</pubDate>
      <link>https://dev.to/travisci/the-cookbook-build-matrix-3okj</link>
      <guid>https://dev.to/travisci/the-cookbook-build-matrix-3okj</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vl7ZVHu6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rhaovmrn9c32jo54xy4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vl7ZVHu6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rhaovmrn9c32jo54xy4b.png" alt="Alt Text" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A build matrix in Travis is made up by several multiple jobs that run in parallel. This can be useful in many cases, but the two primary reasons we see people use matricies is for reducing the overall build execution time and running tests against different versions of runtimes or dependencies to get the best version of the build. Let's learn about Build Matricies in Travis CI. &lt;/p&gt;

&lt;h1&gt;
  
  
  Build Matrix and setting up the .travis.yml
&lt;/h1&gt;

&lt;p&gt;As you know by now, you need to tell Travis which language environment to select for your project. You can do so using the &lt;code&gt;language&lt;/code&gt; key option, in this Cookbook we'll be using PHP. You can specify which PHP versions will the tests be executed. Not introducing patch versions tells Travis to use the latest available, which is sometimes referred to &lt;code&gt;edge&lt;/code&gt;, or if it's the stable version, you guessed it, it's called &lt;code&gt;stable&lt;/code&gt;. So let's start building out our &lt;code&gt;.travis.yml&lt;/code&gt;:&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;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;php&lt;/span&gt;

&lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;5.3.3&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;5.4&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;5.5&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;5.6&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;hhvm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Env Vars
&lt;/h1&gt;

&lt;p&gt;Let's tell Travis to do multiple runs/builds with different sets of &lt;code&gt;env var&lt;/code&gt; values. To do so, add an &lt;code&gt;env key&lt;/code&gt;. Each segment is understood as a different environment and tests are run separately as such. We are going to use &lt;code&gt;PHP_SEGMENT_TEST&lt;/code&gt; later in the file to run tester with the argument of &lt;code&gt;-p&lt;/code&gt; and &lt;code&gt;hhvm&lt;/code&gt; option in HHVM environment, so in your &lt;code&gt;.travis.yml&lt;/code&gt; file, add the &lt;code&gt;env&lt;/code&gt; segment:&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PHP_SEGMENT_TESTRUN="php-cgi"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PHP_SEGMENT_TEST="hhvm"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now simple math would have it, the combination of five PHP versions and the two &lt;code&gt;env vars&lt;/code&gt; generates a total of 10 runs.&lt;/p&gt;

&lt;h1&gt;
  
  
  Dependency installation using Composer
&lt;/h1&gt;

&lt;p&gt;You'll obviously have an install segment in your &lt;code&gt;.travis.yml&lt;/code&gt;. Each sub-segment means one single command. Composer installs your dev dependencies by default. You should use --no-interaction so Composer doesn't ask questions Travis can't answer, and can continue the build. &lt;/p&gt;

&lt;p&gt;You'll want the latest build, so in you &lt;code&gt;.travis.yml&lt;/code&gt; make sure you run the &lt;code&gt;update&lt;/code&gt; flag at &lt;code&gt;before_install&lt;/code&gt;, so it would look like:&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;before_install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;composer self-update&lt;/span&gt;

&lt;span class="na"&gt;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;composer install --no-interaction&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  The Build Matrix
&lt;/h1&gt;

&lt;p&gt;Depending on the configuration above (different segments and sub segments), a build matrix wil be generated. The matrix contains all combinations the environment settings. A single combination is called a job and is run separately. You can modify the matrix in matrix section.&lt;/p&gt;

&lt;p&gt;If you want to exclude a job, use the &lt;code&gt;exclude&lt;/code&gt; key. In our case, we don't want to use -p hhvm parameter for standard PHP versions and -p php-cgi for HHVM:&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;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5.3.3&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PHP_SEGMENT_TEST="hhvm"&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5.4&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TPHP_SEGMENT_TEST="hhvm"&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5.5&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PHP_SEGMENT_TEST="hhvm"&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5.6&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PHP_SEGMENT_TEST="hhvm"&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hhvm&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PHP_SEGMENT_TESTRUN="php-cgi"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To your pleasure, you can define jobs that are allowed to fail without causing the whole build to shown as failed. To do so, declare allow_failures. For our sake, we allow HHVM to fail, lets do this via:&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;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;allow_failures&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hhvm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I only specified the PHP version, not the environment variables. This means all jobs with HHVM version will be allowed to fail/retry (if that is an option you have in your &lt;code&gt;.travis.yml&lt;/code&gt;. Anyway, nevermind the environment variables values. It works with &lt;code&gt;exclude&lt;/code&gt; also.&lt;/p&gt;

&lt;h1&gt;
  
  
  Running the scripts/tests
&lt;/h1&gt;

&lt;p&gt;Tests are run in script segment of the &lt;code&gt;.travis.yml&lt;/code&gt;. Let's assume your tests are in &lt;code&gt;scripts/&lt;/code&gt; folder in your file tree and you provide your own &lt;code&gt;php.ini&lt;/code&gt; in the same folder. Additionally, we can tell &lt;code&gt;TESTER&lt;/code&gt; to display information about skipped tests with the &lt;code&gt;-s&lt;/code&gt; flag and to use value of earlier declared &lt;code&gt;TESTER_SEGMENT_TEST&lt;/code&gt; as PHP binary with the -p flag:&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;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./vendor/bin/tester -p $TESTER_SEGMENT_TEST -s -c ./tests/php.ini ./tests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the build &lt;code&gt;fails&lt;/code&gt; we want to use &lt;code&gt;after_failure&lt;/code&gt; to get the exact values via:&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;after_failure&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Prints *.actual files contents (if not revert) &lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;for i in $(find ./tests -name \*.actual); do echo "--- $i"; cat $i; echo; echo; done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Other services
&lt;/h1&gt;

&lt;p&gt;Travis comes with multiple popular services and has no shortages of them, (e.g. MySQL, Redis, Docker) pre-installed. However, if you need to use for example Redis storage, you can tell Travis in services section via:&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;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis-server&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  DB Init
&lt;/h1&gt;

&lt;p&gt;Depending on what database you chose to use, it can vary -- in this example we are using &lt;code&gt;MySQL&lt;/code&gt;. MySQL runs on 127.0.0.1 and you can log in using travis or root as username. Say you have a DB setup script, and it's in &lt;code&gt;tests/montana/testbase.sql.&lt;/code&gt;, here's a sample segment:&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;before_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mysql -u root -e 'CREATE DATABASE testbase;'&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mysql -u root testbase &amp;lt; tests/montana/testbase.sql&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  .travis.yml in it's final form
&lt;/h1&gt;

&lt;p&gt;After a lot of this segment config, this is what you're left with:&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;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;php&lt;/span&gt;

&lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;5.3.3&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;5.4&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;5.5&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;5.6&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;hhvm&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;TESTER_SEGMENT_TEST="php-cgi"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;TESTER_SEGMENT_TESTRUN="hhvm"&lt;/span&gt;

&lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;allow_failures&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hhvm&lt;/span&gt;

  &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5.3.3&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TESTER_SEGMENT_TEST="hhvm"&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5.4&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TESTER_SEGMENT_TEST="hhvm"&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5.5&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TESTER_SEGMENT_TEST="hhvm"&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5.6&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TESTER_SEGMENT_TEST="hhvm"&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hhvm&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TESTER_SEGMENT_TESTRUN="php-cgi"&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis-server&lt;/span&gt;

&lt;span class="na"&gt;before_install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;composer self-update&lt;/span&gt;

&lt;span class="na"&gt;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;composer install --no-interaction --prefer-source&lt;/span&gt;

&lt;span class="na"&gt;before_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mysql -u root -e 'CREATE DATABASE testbase;'&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mysql -u root testbase &amp;lt; tests/montana/testbase.sql&lt;/span&gt;

&lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./vendor/bin/tester -p $TESTER_SEGMENT_TEST -c ./tests/php.ini -s ./tests/&lt;/span&gt;

&lt;span class="na"&gt;after_failure&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# to find actual variables if needed, a verbose esque way of doing things&lt;/span&gt;
  &lt;span class="c1"&gt;# Prints *.actual files content&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;for i in $(find ./tests -name \*.actual); do echo "--- $i"; cat $i; echo; echo; done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Activate webhook
&lt;/h1&gt;

&lt;p&gt;Go to &lt;a href="http://www.travis-ci.com"&gt;www.travis-ci.com&lt;/a&gt;, and flip switch to &lt;code&gt;ON&lt;/code&gt; for all repositories you'd like to enable. Travis will now add your repository to queue after every pushed commit or created pull-request. After a short while, your repository will be tested. Now if you'd like the opposite, there's a bash script I've created, which I will attach right below this - as some people find this more efficient:&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="c"&gt;#!/usr/bin/env sh&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello from Montana at Travis"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$TRAVIS_PULL_REQUEST&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TRAVIS_PULL_REQUEST&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"false"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;surge &lt;span class="nt"&gt;--project&lt;/span&gt; ./dist &lt;span class="nt"&gt;--domain&lt;/span&gt; auto-deploy-test.surge.sh
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"This is a PR, not deploying"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To know if your build is successful either check the GitHub status, or generate a status image. &lt;/p&gt;

&lt;h1&gt;
  
  
  Congratulations
&lt;/h1&gt;

&lt;p&gt;This is Travis's Build Matrix in a nutshell, it can seem a bit confusing but after going over it a few times, it will start to make sense.&lt;/p&gt;

</description>
      <category>news</category>
      <category>feature</category>
      <category>infrastructure</category>
      <category>community</category>
    </item>
    <item>
      <title>The Cookbook: Jekyll</title>
      <dc:creator>Montana Mendy</dc:creator>
      <pubDate>Mon, 25 Jan 2021 08:24:54 +0000</pubDate>
      <link>https://dev.to/travisci/the-cookbook-jekyll-5f7a</link>
      <guid>https://dev.to/travisci/the-cookbook-jekyll-5f7a</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oMNCzSmP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/x44n0xl7zbu324as5cef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oMNCzSmP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/x44n0xl7zbu324as5cef.png" alt="Header" width="880" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub Pages are an amazing way to host Jekyll pages, but in some cases, you might be interested in running your Jekyll page on a different host (like Azure Web Apps, Heroku, AWS). In this Cookbook let's setup a DevOps Build Pipeline that takes commits, run smoke screen testing, and actually deploying. &lt;/p&gt;

&lt;h1&gt;
  
  
  Getting started with Jekyll
&lt;/h1&gt;

&lt;p&gt;Ideally with Jekyll, you want a compile script (obviously in bash) that traverses to an &lt;code&gt;out/&lt;/code&gt; directory. For sake of this example, you can call the bash script anything but I'm going to call it &lt;code&gt;jekyll.sh&lt;/code&gt;. Your project may require something different, for example &lt;code&gt;npm build&lt;/code&gt; or something to that extent.&lt;/p&gt;

&lt;p&gt;When creating the file tree/structure, let's make sure the &lt;code&gt;out/&lt;/code&gt; directory contains almost or essentially everything you want deployed to &lt;code&gt;gh-pages&lt;/code&gt;. In a case like this, you will 95% of the time have a &lt;code&gt;index.html&lt;/code&gt; file. &lt;/p&gt;

&lt;p&gt;Check this script into your project. Now this is just an example, now let's say the script just reads (remember, your script might just read &lt;code&gt;npm build&lt;/code&gt;:&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Bash
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;#!/bin/bash/env sh &lt;/span&gt;

&lt;span class="c"&gt;# only let the script proceed when started not by a pull request (PR)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$TRAVIS_PULL_REQUEST&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="c"&gt;# you can make this more strict via "==="&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"this is a PR, exiting now"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# enable error reporting to the console &amp;amp; log that into a file entitled "log.txt" &lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="c"&gt;# build site with jekyll, by default to `_site' folder&lt;/span&gt;

bundle &lt;span class="nb"&gt;exec &lt;/span&gt;jekyll build

&lt;span class="c"&gt;# find ./_site -name "*.html" -exec bundle exec htmlbeautifier {} \;&lt;/span&gt;

bundle &lt;span class="nb"&gt;exec &lt;/span&gt;htmlproof ./_site &lt;span class="nt"&gt;--disable-external&lt;/span&gt; &lt;span class="nt"&gt;--check-html&lt;/span&gt; &lt;span class="nt"&gt;--verbose&lt;/span&gt;

&lt;span class="c"&gt;# cleanup using `rm -rf`&lt;/span&gt;

&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ../Montana.github.io.master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Travis and adding Travis to your project
&lt;/h2&gt;

&lt;p&gt;We assume you have one, but if not get a Travis account at &lt;a href="https://travis-ci.com/"&gt;https://travis-ci.com/&lt;/a&gt;. Turn on Travis for the repo in question, using the Travis GUI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encrypted credentials
&lt;/h2&gt;

&lt;p&gt;If you read the Cookbook Series: Encryption, you can most likely skip over this, but if you haven't - when you deploy using Travis, ideally you want to deploy &lt;code&gt;gh-pages&lt;/code&gt; without checking in the necessary credentials to your repo, this can be done using &lt;a href="https://docs.travis-ci.com/user/encrypting-files/"&gt;encryption&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next up, you'll want to generate a SSH key. The advice I always give is to &lt;em&gt;never&lt;/em&gt; reuse SSH keys. To generate a new SSH key, you'll want to open a terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-b&lt;/span&gt; 4096 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"your_email@example.com"&lt;/span&gt; &lt;span class="c"&gt;# in my case "ssh-keygen -t rsa -b 4096 -C "montana@travis-ci.org"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll be prompted to do a few things, one thing you want to remember is you &lt;em&gt;do not&lt;/em&gt; want to include a password, just press &lt;code&gt;enter&lt;/code&gt; when prompted, then follow the next prompt and continue. You'll now want to add the deploy key to your repo, and remember &lt;em&gt;do not&lt;/em&gt; reuse SSH keys. You can do this via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://github.com/&amp;lt;github_username&amp;gt;/&amp;lt;your_repo&amp;gt;/settings/keys &lt;span class="c"&gt;# add the deploy key to your repo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it's time to encrypt the key that was generated using the Travis CLI client. So now let's demonstrate on how we would add your deploy key to your specified repo. &lt;/p&gt;

&lt;h2&gt;
  
  
  Adding your encrypted vars
&lt;/h2&gt;

&lt;p&gt;First, let's open an editor so we can view the &lt;code&gt;dpl key&lt;/code&gt;, so let's run:&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="nb"&gt;cat &lt;/span&gt;github_deploy_key.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use &lt;code&gt;touch&lt;/code&gt;, so instead of &lt;code&gt;cat&lt;/code&gt;, it would be:&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="nb"&gt;touch &lt;/span&gt;github_deploy_key.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that you have the key, make sure the proper repo is conditioned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://github.com/&amp;lt;github_username&amp;gt;/&amp;lt;your_repo&amp;gt;/settings/keys &lt;span class="c"&gt;# add the deploy key to your repo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's use Travis again from the CLI again to login:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;travis login &lt;span class="nt"&gt;--org&lt;/span&gt; &lt;span class="nt"&gt;--auto&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll then want to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;travis encrypt-file &lt;span class="s1"&gt;'github_deploy_key'&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure you add your &lt;code&gt;PUBLIC&lt;/code&gt; key as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="s1"&gt;'github_deploy_key.enc'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The bash script I've coded below automates the above process essentially, I did this to make it a bit easier on the Travis CI user, for the sake of time lets say this bash script I created is called &lt;code&gt;dpl_key&lt;/code&gt;:&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="c"&gt;#!/bin/bash/env sh &lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GITHUB_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"GITHUB_TOKEN environment variable is missing"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Travis dpl_key generator"&lt;/span&gt; 
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"This generates a public/private dpl_key, add the public key as a deploy key
  with write access to the origin remote github repo, encrypt the private key as
  github_deploy_key.enc and add the configuration necessary to use it in your .travis.yml file"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Give it a shot:"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"  GITHUB_TOKEN=&lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt;cat ~/secret/GITHUB_TOKEN&lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt; ./generate_travis_deploy_key"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"where ~/secret/GITHUB_TOKEN is a file containing a github token with write access to the current repository : (origin)"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"You must have the Travis executable installed on your system and available in the PATH"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
  &lt;span class="nb"&gt;exit
&lt;/span&gt;&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git config &lt;span class="nt"&gt;--get&lt;/span&gt; remote.origin.url&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;reponame&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$url&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;/ &lt;span class="nt"&gt;-f2&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-f1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# generate a new private and public key&lt;/span&gt;

ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-b&lt;/span&gt; 4096 &lt;span class="nt"&gt;-f&lt;/span&gt; github_deploy_key &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="nv"&gt;$url&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; 1&amp;gt;/dev/null

&lt;span class="nv"&gt;pubkey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;github_deploy_key.pub&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# add the PUBLIC key to the github repository as a deploy key with write access&lt;/span&gt;

curl https://github.com/&amp;lt;github_username&amp;gt;/&amp;lt;your_repo&amp;gt;/settings/keys &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: token &lt;/span&gt;&lt;span class="nv"&gt;$GITHUB_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--data&lt;/span&gt; @- &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
{
  "title": "travis deploy key",
  "key": "&lt;/span&gt;&lt;span class="nv"&gt;$pubkey&lt;/span&gt;&lt;span class="sh"&gt;",
  "read_only": false
}
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;&lt;span class="c"&gt;# use travis to encrypt the private key as github_deploy_key.enc and remove the private key&lt;/span&gt;

travis encrypt-file github_deploy_key &lt;span class="nt"&gt;--add&lt;/span&gt; &lt;span class="nt"&gt;--no-interactive&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; /tmp/github_deploy_key &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;--pro&lt;/span&gt;
git add github_deploy_key.enc

&lt;span class="c"&gt;# cleaning&lt;/span&gt;

&lt;span class="nb"&gt;rm &lt;/span&gt;github_deploy_key
&lt;span class="nb"&gt;rm &lt;/span&gt;github_deploy_key.pub

&lt;span class="c"&gt;# bash script by montana mendy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  .travis.yml
&lt;/h2&gt;

&lt;p&gt;So, this is a &lt;code&gt;.travis.yml&lt;/code&gt; file I've created, as you can see if you use my config it will automate the deployment for you, if you'd like to deploy manually, then just remove the line:&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;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;generic&lt;/span&gt; &lt;span class="c1"&gt;# this doesn't install any environment at all &lt;/span&gt;

&lt;span class="na"&gt;before_install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;bash chmod +x ./dpl_key.sh&lt;/span&gt; &lt;span class="c1"&gt;# will give proper permissions via chmod to both scripts &lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;bash chmod +x ./jekyll.sh&lt;/span&gt;

&lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

&lt;span class="na"&gt;before_deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;openssl aes-256-cbc -K $encrypted_0a644212b3ae3_key -iv $encrypted_0a644212b3ae3_key -in deploy_key.enc -out deploy_key -d&lt;/span&gt;


&lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pages&lt;/span&gt;
  &lt;span class="na"&gt;local_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;out&lt;/span&gt;
  &lt;span class="na"&gt;deploy_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy_key&lt;/span&gt;
  &lt;span class="na"&gt;edge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you should have 3 files, the ones we have talked about, &lt;code&gt;jekyll.sh&lt;/code&gt;, &lt;code&gt;deploy_key.enc&lt;/code&gt; and your &lt;code&gt;.travis.yml&lt;/code&gt;. Make sure you've logged into Travis, let Travis know about the repo via syncing, once you push to GitHub it will compile and deploy your source, either using my bash script or doing it step by step. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope you learned some niche ways on deploying source while using Travis, until next time! &lt;/p&gt;

</description>
      <category>news</category>
      <category>feature</category>
      <category>infrastructure</category>
      <category>community</category>
    </item>
    <item>
      <title>The Build, Test, Nuke Pattern</title>
      <dc:creator>Montana Mendy</dc:creator>
      <pubDate>Thu, 21 Jan 2021 03:22:46 +0000</pubDate>
      <link>https://dev.to/travisci/the-build-test-nuke-pattern-30c3</link>
      <guid>https://dev.to/travisci/the-build-test-nuke-pattern-30c3</guid>
      <description>&lt;h1&gt;
  
  
  The Build, Test, Nuke Pattern
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;A Tutorial on Testing Etiquette in the Age of Ephemeral Computing&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nothing lasts forever in the world of ephemeral computing. It’s the nature of the beast. Today, more companies are maximizing their IT budgets by practicing the principles of infrastructure as code (IaC). They’re creating and destroying virtual assets on demand in order to meet the needs of the moment.&lt;/p&gt;

&lt;p&gt;Paying only for what you use makes sense technically and financially. IaC offers a lot of benefits, but it does take some getting used to, particularly with regard to resource management.&lt;/p&gt;

&lt;p&gt;There’s a certain etiquette involved when a lot of people are using a common set of resources. In a way, being part of an IaC environment is similar to using the laundry room in an apartment building. You need to be aware that other people are using the washers, dryers and folding tables. Thus, you need to keep moving your clothes along from washer to dryer in a timely manner, and you need to clean up after yourself, always.&lt;/p&gt;

&lt;p&gt;The same is true in ephemeral computing. There is nothing more irritating than testing on a virtual machine that is all clogged up with useless applications and components left behind from previous tests. Not only do such remnants take up valuable computing resources, but they might also compromise the outcome of your testing. &lt;/p&gt;

&lt;p&gt;When running tests in an ephemeral, IaC environment, a good pattern to follow is one that I call the Build, Test, Nuke pattern. Let’s explore the pattern using an example from a set of unit tests I created in my &lt;a href="https://github.com/reselbob/denodemo"&gt;Deno demonstration project&lt;/a&gt; and ran on Travis CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Build, Test, Nuke
&lt;/h2&gt;

&lt;p&gt;The structure of the Build, Test, Nuke pattern is to divide the testing event into three stages. In the first stage, Build, your testing script gets the source code from a source control management service, such as GitHub, and builds the required dependencies into a deployment unit, such as a Docker container. In the second stage, Test, the script tests the artifact. Then, in the third stage, Nuke, your script destroys the deployment artifacts used in the testing, removing them from both memory and disk. (See figure 1 below.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hEzeeSwo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2czkgqcjdpfbb653z9cv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hEzeeSwo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2czkgqcjdpfbb653z9cv.png" alt="Nuke" width="787" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Figure 1: The Build, Test, Nuke pattern&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The benefit of the pattern is apparent. Your scripts are using only the resources needed, when they’re needed. For a small application, using the pattern might seem trivial. But, when you get into an application that has a dozen dependencies running in separate processes that put pressure on both memory and network IO, leaving them up and running after testing is done can be a significant risk. Destroying everything when testing is over addresses this risk head-on.&lt;/p&gt;

&lt;p&gt;Now that we’ve covered the concept behind the Build, Test, and Nuke pattern, let’s take a look at how it’s implemented when running a set of unit tests under Travis CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting Build, Nuke, Test into Action
&lt;/h2&gt;

&lt;p&gt;As mentioned above, I use the Build, Nuke and Test pattern in a set of HTTP tests I created for an application in my &lt;a href="https://deno.land/"&gt;Deno&lt;/a&gt; demonstration project, which you can find [here].(&lt;a href="https://github.com/reselbob/denodemo"&gt;https://github.com/reselbob/denodemo&lt;/a&gt; The application is called &lt;a href="https://github.com/reselbob/denodemo/tree/master/simplecalc_"&gt;SimpleCalc&lt;/a&gt;. SimpleCalc is an API that exposes the math operations &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;subtract&lt;/code&gt;, &lt;code&gt;multiply&lt;/code&gt; and &lt;code&gt;divide&lt;/code&gt;. The API runs as a web application over HTTP.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Deno?
&lt;/h2&gt;

&lt;p&gt;Deno is a next-generation programming framework developed by Ryan Dahl, the creator of Node.js. Deno runs using the V8 JavaScript, as does Node.js, but Deno uses the Typescript language to program. Deno also improves upon Node.js in other ways, such as the way dependencies are stored and runtime permissions are granted. For more information about Deno, visit the website at: &lt;a href="https://deno.land/"&gt;https://deno.land/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The way the HTTP test works is the script creates the web server that hosts the SimpleCalc API in a &lt;a href="https://www.docker.com/resources/what-container"&gt;Docker&lt;/a&gt; &lt;a href="https://www.docker.com/resources/what-container"&gt;container&lt;/a&gt;. Then, once the SimpleCalc API server is up and running, a set of Deno tests are run. After the tests are run, the test script destroys both the container in which the SimpleCalc API server is running and the &lt;a href="https://stackoverflow.com/questions/23735149/what-is-the-difference-between-a-docker-image-and-a-container"&gt;container image&lt;/a&gt; that’s used to create the container for the SimpleCalc API. (You can think of a container image as the template that describes the container that will run in memory.)&lt;/p&gt;

&lt;p&gt;Listing 1 below shows the Bash script that creates the container, runs the HTTP tests, and then destroys the container and container image.&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="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ..

docker build &lt;span class="nt"&gt;-t&lt;/span&gt; mydenoserver &lt;span class="nb"&gt;.&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; simplecalc &lt;span class="nt"&gt;-p&lt;/span&gt; 7700:7700 mydenoserver

deno &lt;span class="nb"&gt;test&lt;/span&gt;  &lt;span class="nt"&gt;--allow-net&lt;/span&gt; &lt;span class="nt"&gt;--allow-env&lt;/span&gt; &lt;span class="nt"&gt;--allow-read&lt;/span&gt; &lt;span class="nt"&gt;--allow-write&lt;/span&gt; &lt;span class="nt"&gt;--reload&lt;/span&gt;

docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; simplecalc
docker rmi &lt;span class="nt"&gt;-f&lt;/span&gt; mydenoserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Listing 1: The Bash script that implements the Build, Test and Nuke pattern&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice that the Build phase takes place at lines 4 and 5. The script uses the Docker &lt;a href="https://docs.docker.com/engine/reference/commandline/build/"&gt;build&lt;/a&gt; command to create a container image named mydenoserver using the default &lt;a href="https://github.com/reselbob/denodemo/blob/master/simplecalc/Dockerfile"&gt;Dockerfile&lt;/a&gt; stored along with the source code. (See line 4 above.) Then, at line 5, the script executes &lt;a href="https://docs.docker.com/engine/reference/commandline/run/"&gt;docker run&lt;/a&gt; to run a container named &lt;code&gt;simplecalc&lt;/code&gt; using the container image &lt;code&gt;mydenoserver&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Line 7 in listing 1 above invokes the unit tests that are stored in the test directory of the &lt;code&gt;SimpleCalc&lt;/code&gt; app source code files. (The Deno test looks for test files in a directory named &lt;code&gt;test&lt;/code&gt; by default.)&lt;/p&gt;

&lt;p&gt;Listing 2 below shows an excerpt from the test file &lt;a href="https://github.com/reselbob/denodemo/blob/master/simplecalc/test/api_tests.ts"&gt;api_tests.ts&lt;/a&gt;. Notice at line 9 that the test accesses the SimpleCalc API’s add operation by way of the webserver running at &lt;a href="http://0.0.0.0:7700/sum/8,4,3"&gt;http://0.0.0.0:7700/sum/8,4,3&lt;/a&gt;. The IP address 0.0.0.0 indicates the source address for the local computer on which the test is running. The SimpleCalc API is listening for traffic on port 7700. The /sum/8,4.3 segment of the URL is special to the SimpleCalc API. It describes the sum operation and an array of integers that will be summed up by the operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;assertEquals&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://deno.land/std/testing/asserts.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// The test, Can add from API, is an excerpt from a set of many tests&lt;/span&gt;
&lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Can add from API&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`http://0.0.0.0:7700/sum/8,4,3`&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Listing 2: An excerpt from the test of HTTP tests that exercise the SimpleCalc API.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The important thing to know about listing 2 above is that it describes a test that is run against a container that hosts the web server, and that container was created on demand as part of the testing process.&lt;br&gt;
After the test is completed, the Bash script controlling the entire process will issue these two commands as shown below, as well as above in listing 1 at lines 9 and 10:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; simplecalc
docker rmi &lt;span class="nt"&gt;-f&lt;/span&gt; mydenoserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the commands that remove both the container and the container image from the host environment. These two lines fulfill the last part of the Build, Test, Nuke pattern. As you can see, the container and the container image are removed completely from the virtual machine host.&lt;/p&gt;

&lt;p&gt;Listing 3 below shows the &lt;code&gt;.travis.yml&lt;/code&gt; file that gets run when new or adjusted code is committed to the demonstration Deno project.&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;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
&lt;span class="na"&gt;os&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker&lt;/span&gt;
&lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
&lt;span class="na"&gt;before_install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pwd&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl -fsSL https://deno.land/x/install/install.sh | sh&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ls -l $HOME/.deno&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export DENO_INSTALL="$HOME/.deno"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export PATH="$DENO_INSTALL/bin:$PATH"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deno run https://deno.land/std/examples/welcome.ts&lt;/span&gt;

&lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cd ./simplecalc/test/&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sh run_test.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Listing 3: The Travis.yml file that installs Deno executes the script run_test.sh, which implements the Build, Test, Nuke pattern in the Travis runtime environment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of the nice features of Travis CI is that I can register the Deno demonstration project that’s hosted on GitHub with Travis. Once registered, Travis will install a webhook in the GitHub repo that makes it so when code is committed to the repo, the repo will be cloned automatically into a Travis CI virtual machine dedicated to my testing session. Travis looks for the &lt;code&gt;.travis.yml&lt;/code&gt; in the source code and then, once identified, will configure the virtual machine according to settings in the &lt;code&gt;.travis.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;In this case, the instructions to install Deno are at lines 8 through 14 in listing 3 above. The instruction to navigate to the directory that has the Bash script that controls the testing process is at line 17. The instruction to execute the Bash script is at line 18.&lt;/p&gt;

&lt;p&gt;Remember, the Bash script contains all the instructions to execute the Build, Test, and Nuke pattern. Mission accomplished!&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting It All Together
&lt;/h2&gt;

&lt;p&gt;The Build, Test, and Nuke pattern is simple and powerful. Using it consistently as part of your CI/CD process will help you run your tests as a reliable, good neighbor in the host runtime environment, whether they’re running on your local machine, under Travis or anywhere else in the cloud.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>container</category>
      <category>testing</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>The Cookbook: Fable</title>
      <dc:creator>Montana Mendy</dc:creator>
      <pubDate>Mon, 18 Jan 2021 11:03:44 +0000</pubDate>
      <link>https://dev.to/travisci/the-cookbook-fable-n73</link>
      <guid>https://dev.to/travisci/the-cookbook-fable-n73</guid>
      <description>&lt;p&gt;Fable produces readable JavaScript code compatible with ES2015 standards and popular tooling like Webpack, which you've probably heard of if you've ever used React. Let's start this Fable. &lt;/p&gt;

&lt;h2&gt;
  
  
  Build Fable with Travis CI
&lt;/h2&gt;

&lt;p&gt;Hey builders let's get to building Fable with Travis CI! Let's start out with your &lt;code&gt;.travis.yml&lt;/code&gt; file:&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;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;minimal&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker&lt;/span&gt;

&lt;span class="na"&gt;sudo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt;

&lt;span class="na"&gt;before_install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker pull vbfox/fable-build&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;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CI"&lt;/span&gt;
      &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker run -v "${PWD}:/app" -w "/app" vbfox/fable-build bash -c "yarn &amp;amp;&amp;amp; yarn postinstall &amp;amp;&amp;amp; yarn build"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's sometimes issues with &lt;code&gt;Fable&lt;/code&gt; for whatever reason with syntax errors, so you may want to take the time and &lt;code&gt;lint&lt;/code&gt; your &lt;code&gt;.travis.yml&lt;/code&gt; file, you can do this via running &lt;code&gt;travis lint&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;package.json&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;package.json&lt;/code&gt; contains something like the following:&lt;br&gt;
&lt;/p&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;"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;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack-dev-server"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack -p"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"postinstall"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"paket restore &amp;amp;&amp;amp; paket generate-load-scripts -f netstandard2.0 -t fsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"predeploy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"deploy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gh-pages -d docs"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see &lt;code&gt;webpack&lt;/code&gt; is being triggered there as well. That's it - you've now built Fable in Travis CI! Phew, that was easier than we thought.&lt;/p&gt;

</description>
      <category>news</category>
      <category>feature</category>
      <category>infrastructure</category>
      <category>community</category>
    </item>
    <item>
      <title>The Cookbook: Branch Flow</title>
      <dc:creator>Montana Mendy</dc:creator>
      <pubDate>Tue, 12 Jan 2021 03:29:35 +0000</pubDate>
      <link>https://dev.to/travisci/the-cookbook-branch-flow-1ek6</link>
      <guid>https://dev.to/travisci/the-cookbook-branch-flow-1ek6</guid>
      <description>&lt;p&gt;It's important when using multiple branches in your repository to define which branches to build to, and which branches not to build to. Let's get started.&lt;/p&gt;

&lt;h1&gt;
  
  
  Branch Flow
&lt;/h1&gt;

&lt;p&gt;Travis CI uses the &lt;code&gt;.travis.yml&lt;/code&gt; file from your project structure, once you've configured your flow via the &lt;code&gt;.travis.yml&lt;/code&gt; file, you can trigger a build by pushing changes through the CLI using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
git add &lt;span class="nb"&gt;.&lt;/span&gt; 
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Travis build branch"&lt;/span&gt; 
git remote add origin remote repository URL
git remote &lt;span class="nt"&gt;-v&lt;/span&gt; 
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can tell Travis to build multiple branches using &lt;code&gt;blacklists&lt;/code&gt; or &lt;code&gt;whitelists&lt;/code&gt;. More specifically you can define which branches to build using a &lt;code&gt;whitelist&lt;/code&gt;, or on the flip side you can use &lt;code&gt;blacklist&lt;/code&gt;. You can blacklist branches that you do not want to be built via the following:&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;# blacklist (branches you don't want to be built) &lt;/span&gt;
&lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;except&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;legacy&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;edge&lt;/span&gt;

&lt;span class="c1"&gt;# whitelist&lt;/span&gt;
&lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;stable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you specify both &lt;code&gt;whitelist&lt;/code&gt; and &lt;code&gt;blacklist&lt;/code&gt;, only takes precedence over except. By default, let's say you have a &lt;code&gt;gh-pages&lt;/code&gt; branch, that branch is not built unless you add it to the &lt;code&gt;whitelist&lt;/code&gt; explicitly. When deploying to your version control, or if you're using Apache SVN (Subversion), in some cases, it may reset your working directory, it does this via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a cursory cautionary move, you can add &lt;code&gt;skip_cleanup&lt;/code&gt; to your &lt;code&gt;.travis.yml&lt;/code&gt; file. So after, your &lt;code&gt;yml&lt;/code&gt; file might look 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;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;skip_cleanup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there's anything you want to add before you deploy, you can obviously add &lt;code&gt;before_deploy&lt;/code&gt;. This is also true for an inverse method, for after deployment via &lt;code&gt;after_deploy&lt;/code&gt;. &lt;/p&gt;

</description>
      <category>news</category>
      <category>feature</category>
      <category>infrastructure</category>
      <category>community</category>
    </item>
    <item>
      <title>Deploying and Using WebAssembly Under Deno on the Server Side Using Travis CI</title>
      <dc:creator>Montana Mendy</dc:creator>
      <pubDate>Thu, 07 Jan 2021 11:05:23 +0000</pubDate>
      <link>https://dev.to/travisci/deploying-and-using-webassembly-under-deno-on-the-server-side-using-travis-ci-5h6o</link>
      <guid>https://dev.to/travisci/deploying-and-using-webassembly-under-deno-on-the-server-side-using-travis-ci-5h6o</guid>
      <description>&lt;p&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%2Fi%2F8cddl3o7qpwnwty52jmo.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%2Fi%2F8cddl3o7qpwnwty52jmo.png" alt="Header"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Containers are a game changer in software development. They provide the operational isolation found in virtual machines without the overhead. Whereas it can take a virtual machine minutes to spin up, you can have a container up and running in seconds, or even in some cases milliseconds.&lt;/p&gt;

&lt;h1&gt;
  
  
  Getting started
&lt;/h1&gt;

&lt;p&gt;Containers have become central to modern distributed application architecture, particularly now that container orchestration technologies such as Kubernetes and Docker Swarm have become commonplace in the enterprise. However, as popular as container technology is for implementing isolated processes for use in a distributed application, there is an alternative. That alternative is &lt;a href="https://webassembly.org/" rel="noopener noreferrer"&gt;WebAssembly&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;WebAssembly is a compiled binary that operates inside a runtime unit called a WebAssembly VM, or virtual machine. WebAssembly has been around for a while on the client side, and all the major web browsers support it. But you can also run it on the server side. All you need is to have a programming framework that supports server-side WebAssembly VM.&lt;/p&gt;

&lt;p&gt;Deno — an emerging language from Ryan Stahl, the creator of Node.js — supports WebAssembly. Deno uses the V8 JavaScript runtime found in Chrome on the server side, as does Node.js. The WebAssembly VM is built right into V8, so Deno supports WebAssembly.&lt;/p&gt;

&lt;p&gt;In this tutorial, I am going to show how to use Travis CI to build a WebAssembly binary written in Rust, and then run a demonstration application I wrote in Deno that uses the WebAssembly as an internal component.&lt;/p&gt;

&lt;p&gt;This tutorial is high-level, and you don’t need to know the details of Rust or Deno to get benefit from reading it. The hope is that the tutorial will spur your interest to delve further into the technologies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the demonstration application
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/reselbob/deno-wasm" rel="noopener noreferrer"&gt;demonstration project&lt;/a&gt; that accompanies this article is a Deno application that uses a WebAssembly binary. The Deno code uses logic in the WebAssembly to do a calculation. The calculation that the WebAssembly binary provides is encapsulated into a function named cube(). The function cubes a number that is provided as a parameter. For example, when the number 3 is passed to the function, as cube(3), the function returns 27.&lt;/p&gt;

&lt;p&gt;As shown in figure 1 below, the WebAssembly (WASM) binary is written in the programming language &lt;a href="https://www.rust-lang.org/" rel="noopener noreferrer"&gt;Rust&lt;/a&gt;. Rust is a compiled language. A programmer writes some code in text and stores it in a file named lib.rs. The code is passed to the Rust WASM compiler. The result is a WebAssembly binary that’s used by the Deno code.&lt;/p&gt;

&lt;p&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%2Fi%2Ffcpm4qbfvo1h14u19a80.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%2Fi%2Ffcpm4qbfvo1h14u19a80.png" alt="Fig1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Figure 1: Deno uses a WebAssembly binary programmed in Rust.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s the high-level view. Let’s take a look at some of the detail involved in creating the WebAssembly binary in Rust and then consuming the binary in Deno.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examining the WebAssembly code
&lt;/h2&gt;

&lt;p&gt;The work required to create a WebAssembly binary in Rust is consolidated using Rust’s &lt;code&gt;crate&lt;/code&gt; packaging technology.&lt;/p&gt;

&lt;p&gt;The Rust programming community provides a packaging ecosystem similar to &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt; for Node.js and to Java’s &lt;a href="https://maven.apache.org/what-is-maven.html" rel="noopener noreferrer"&gt;Maven&lt;/a&gt;. Packages under Rust are called &lt;code&gt;crates&lt;/code&gt;. The standard file that describes a crate is named &lt;a href="https://doc.rust-lang.org/cargo/reference/manifest.html" rel="noopener noreferrer"&gt;&lt;code&gt;Cargo.toml&lt;/code&gt;&lt;/a&gt;. It’s similar to the way Node.js uses &lt;a href="https://docs.npmjs.com/files/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt; to describe a Node.js package. (I’ll explain the &lt;code&gt;Cargo.toml&lt;/code&gt; file for the demonstration Rust binary in a moment.)&lt;/p&gt;

&lt;p&gt;The way you install Rust packages from an external Rust package repository is to use the command &lt;a href="https://doc.rust-lang.org/cargo/commands/cargo-install.html" rel="noopener noreferrer"&gt;cargo install &lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Creating a WebAssembly in Rust can be a detail-laden undertaking. To simplify the process, we’re going to use an external package called wasm-pack. &lt;a href="https://rustwasm.github.io/wasm-pack/book/" rel="noopener noreferrer"&gt;wasm-pack&lt;/a&gt; will execute against the Cargo.toml file that defines the WebAssembly binary we’re going to create. (Keep in mind that the standalone WebAssembly binary is considered a package.)&lt;/p&gt;

&lt;p&gt;Listing 1 below shows the Cargo.toml file that describes the Rust project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cube_it"&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.9.0"&lt;/span&gt;
&lt;span class="n"&gt;edition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2018"&lt;/span&gt;
&lt;span class="n"&gt;authors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Bob Reselman &amp;lt;reselbob@gmail.com&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"A small project to demonstrate how to run to create a WebAssembly binary"&lt;/span&gt;
&lt;span class="n"&gt;license&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"MIT/Apache-2.0"&lt;/span&gt;
&lt;span class="n"&gt;repository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://github.com/reselbob/deno-wasm"&lt;/span&gt;

&lt;span class="cs"&gt;# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;wasm&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bindgen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.2"&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"cdylib"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"rlib"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Listing 1: The Cargo.toml file&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lines 1 through 12 above provide typical metadata about the project. Notice in line 1 that the arbitrary name of the package is &lt;code&gt;cube_it&lt;/code&gt;. This makes sense because the WebAssembly binary that this package definition creates has a function that will cube a number.&lt;/p&gt;

&lt;p&gt;Lines 13 and 14 indicate that the Rust project will use an additional package, wasm-bindgen. The purpose of wasm-bindgen is to provide interoperability between the Rust binary and JavaScript code. Deno programming is done in TypeScript. However, at runtime TypeScript &lt;a href="https://encyclopedia2.thefreedictionary.com/transpile" rel="noopener noreferrer"&gt;transpiles&lt;/a&gt; into JavaScript. Using &lt;code&gt;wasm-bindgen&lt;/code&gt; allows the Rust code to access JavaScript functions such as logging and the JavaScript DOM model, so &lt;code&gt;wasm-bindgen&lt;/code&gt; is defined in &lt;code&gt;Cargo.toml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Lines 16 and 17 assign the library &lt;a href="https://doc.rust-lang.org/nightly/edition-guide/rust-2018/platform-and-target-support/cdylib-crates-for-c-interoperability.html" rel="noopener noreferrer"&gt;cdylib&lt;/a&gt; to crate-type. This provides interoperability with C code. In addition, crate-type is assigned the value &lt;a href="https://doc.rust-lang.org/reference/linkage.html" rel="noopener noreferrer"&gt;rlib&lt;/a&gt; to indicate that a Rust library will be produced.&lt;/p&gt;

&lt;p&gt;Listing 2 below shows the Rust code for the function &lt;code&gt;cube(x: u32)&lt;/code&gt;. The function will reside in the file &lt;code&gt;lib.rs&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;cube&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Listing 2: The Rust code in &lt;code&gt;lib.rs&lt;/code&gt; that publishes the cube function&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The logic in the function &lt;code&gt;cube(x: u32)&lt;/code&gt; will be consumed by the Deno code.&lt;/p&gt;

&lt;p&gt;Once the Rust package is declared in &lt;code&gt;Cargo.toml&lt;/code&gt; and the &lt;code&gt;cube()&lt;/code&gt; function is defined in &lt;code&gt;lib.rs&lt;/code&gt;, we’ll need to create the Deno code to consume the WebAssembly binary that’s created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running WebAssembly under Deno
&lt;/h2&gt;

&lt;p&gt;Listing 3 below shows the contents of the file &lt;a href="https://github.com/reselbob/deno-wasm/blob/master/main.ts" rel="noopener noreferrer"&gt;&lt;code&gt;main.ts&lt;/code&gt;&lt;/a&gt;. This file contains the Deno code that consumes the WebAssembly binary that contains the function &lt;code&gt;cube()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;wasmCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;     &lt;span class="n"&gt;Deno&lt;/span&gt;&lt;span class="nf"&gt;.readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./rust_for_deno/target/wasm32-unknown-unknown/release/cube_it.wasm"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;wasmModule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;WebAssembly&lt;/span&gt;&lt;span class="nf"&gt;.Module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wasmCode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;wasmInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;WebAssembly&lt;/span&gt;&lt;span class="nf"&gt;.Instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wasmModule&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cube&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wasmInstance&lt;/span&gt;&lt;span class="py"&gt;.exports&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="nf"&gt;.log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cube&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="nf"&gt;.log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cube&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="nf"&gt;.log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cube&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="nf"&gt;.log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cube&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Listing 3: The Deno code that consumes the WebAssembly binary&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lines 1 through 5 do the work of loading the WebAssembly into the V8 virtual machine and making the &lt;code&gt;cube()&lt;/code&gt; function accessible to the Deno code. Lines 7 through 10 execute the &lt;code&gt;cube()&lt;/code&gt; function four times, each time with a different parameter value, and then write the output of each call to the console.&lt;/p&gt;

&lt;p&gt;Now that we have both the Rust WebAssembly and Deno projects coded and ready to go, we need to create a &lt;code&gt;travis.yml&lt;/code&gt; file that will build the WebAssembly binary, as well as install the Deno runtime environment and run the Deno code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with the &lt;code&gt;.travis.yml&lt;/code&gt; file
&lt;/h2&gt;

&lt;p&gt;One of the nice features of Travis CI is that it will execute a run script in response to an event generated from a webhook installed in a GitHub repository that is bound to Travis CI. Under Travis CI, the run script has a standard name, &lt;code&gt;.travis.yml.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/reselbob/deno-wasm" rel="noopener noreferrer"&gt;deno-wasm&lt;/a&gt; demonstration project for this article stored on GitHub has a webhook installed that sends an event notification to Travis CI whenever code is committed to the &lt;code&gt;deno-wasm&lt;/code&gt; repository. Travis CI receives the event notification and clones the code into a runtime virtual machine created just for the project. Then, it runs the instructions in the expected &lt;code&gt;.travis.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Listing 4 below shows the contents of the &lt;code&gt;.travis.yml&lt;/code&gt; file.&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;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rust&lt;/span&gt;
&lt;span class="na"&gt;os&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu&lt;/span&gt;
&lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
&lt;span class="na"&gt;before_install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pwd&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;rustc --version&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sudo apt-get update&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sudo apt-get -y install libssl-dev pkg-config&lt;/span&gt; 
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;rustup target add wasm32-unknown-unknown&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cargo install wasm-pack&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export PATH="$HOME/.cargo/bin:$PATH"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cd ./rust_for_deno&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;wasm-pack build&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cd ..&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl -fsSL https://deno.land/x/install/install.sh | sh&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ls -l $HOME/.deno&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export DENO_INSTALL="$HOME/.deno"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export PATH="$DENO_INSTALL/bin:$PATH"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deno run https://deno.land/std/examples/welcome.ts&lt;/span&gt;

&lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deno run --allow-read main.ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Listing 4: The travis.yml file for building and running the deployment on Travis CI&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first thing to notice about the &lt;code&gt;.travis.yml&lt;/code&gt; file in listing 4 above is that Travis CI supports the Rust programming language right out of the box. All you need to do is set the &lt;code&gt;language&lt;/code&gt; definition, as shown at line 1.&lt;/p&gt;

&lt;p&gt;The work of creating the WebAssembly binary and installing Deno is done in the &lt;code&gt;before_install&lt;/code&gt; section, starting at line 5.&lt;/p&gt;

&lt;p&gt;Lines 7 and 8 are convenience instructions that report the present working directory &lt;code&gt;(pwd)&lt;/code&gt; and the current version of the Rust compiler installed &lt;code&gt;(rustc --version)&lt;/code&gt;. This is done just to make sure that the &lt;code&gt;.travis.yml&lt;/code&gt; script is talking to the Travis CI runtime in a predictable manner.&lt;/p&gt;

&lt;p&gt;Lines 9 and 10 install some added packages that Ubuntu needs in order to execute the &lt;code&gt;wasm-pack&lt;/code&gt; instruction that will come.&lt;/p&gt;

&lt;p&gt;Lines 11 through 15 do the work of installing the &lt;code&gt;wasm-pack&lt;/code&gt; Rust package and creating the WebAssembly binary using &lt;code&gt;wasm-pack&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Deno is not installed in the Travis CI runtime environment by default. Thus, lines 17 through 20 do the work of installing it and configuring the &lt;code&gt;DENO_INSTALL&lt;/code&gt; environment variable. Also, the &lt;code&gt;PATH&lt;/code&gt; environment variable is updated to accommodate the Deno binaries.&lt;/p&gt;

&lt;p&gt;Line 21 runs a Deno &lt;code&gt;Hello World&lt;/code&gt; program downloaded from the internet, to verify that Deno is up and running.&lt;/p&gt;

&lt;p&gt;As mentioned earlier, the code that uses the &lt;code&gt;cube()&lt;/code&gt; function in the WebAssembly binary is stored in the file &lt;code&gt;main.ts&lt;/code&gt;. &lt;code&gt;main.ts&lt;/code&gt; is called within the script section of the &lt;code&gt;.travis.yml&lt;/code&gt; file at line 24 above.&lt;/p&gt;

&lt;p&gt;The output of the call to the &lt;code&gt;main.ts&lt;/code&gt; file is shown below in figure 2.&lt;/p&gt;

&lt;p&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%2Fi%2Fe9xc5m0qticd22p287q3.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%2Fi%2Fe9xc5m0qticd22p287q3.png" alt="Fig2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Figure 2: The output from the demonstration application running under Travis CI&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So there you have it. We’ve just used the Travis CI runtime environment to create a WebAssembly binary and run it in a Deno program. Granted, this is just a small demonstration program, but it does reveal the critical aspects of using WebAssembly to provide services to interested consumers in an isolated manner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;It’s interesting that Solomon Hykes, the co-founder of Docker, &lt;a href="https://conferences.codegram.com/talks/bringing-webassembly-outside-the-web-with-wasi-fsf2019" rel="noopener noreferrer"&gt;said this&lt;/a&gt; about WebAssembly:&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;“If WASM+WASI [WebAssembly and its system interface] existed in 2008, we wouldn’t have needed to create Docker.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;Server-side WebAssembly has significant potential. Its elegance and power make it an attractive technology for the fast execution of complex algorithms on the server side. Consequently, there are a growing number of projects that are publishing tools for WebAssembly development. You can already create WASM binaries in Go, Rust, C# and C/C++. In addition, there are initiatives to bring support for WebAssembly to a wider array of languages. For example, &lt;a href="https://www.assemblyscript.org/" rel="noopener noreferrer"&gt;AssemblyScript&lt;/a&gt; is intended to allow developers to create WebAssembly binaries from JavaScript code.&lt;/p&gt;

&lt;p&gt;The opportunities at hand are significant. Of course, in order to make WebAssembly a viable addition to your programming toolbox, you will need to take the time to master the details of the technology. But, as current trends reveal, WebAssembly is becoming a mainstay on the server side, and realizing its value will be an investment that will yield dramatic returns.&lt;/p&gt;

&lt;p&gt;WebAssembly is here. The time to take advantage of the opportunities at hand is now.&lt;/p&gt;

</description>
      <category>news</category>
      <category>feature</category>
      <category>infrastructure</category>
      <category>community</category>
    </item>
    <item>
      <title>The Cookbook with Bash</title>
      <dc:creator>Montana Mendy</dc:creator>
      <pubDate>Mon, 21 Dec 2020 02:19:51 +0000</pubDate>
      <link>https://dev.to/travisci/the-cookbook-with-bash-2a1l</link>
      <guid>https://dev.to/travisci/the-cookbook-with-bash-2a1l</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ojq8bAGh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rflfkyq63m1i3iiyvbww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ojq8bAGh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rflfkyq63m1i3iiyvbww.png" alt="Bash" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Many projects on GitHub use Travis to automatically execute certain scripts on every build. Among these many scripts, there is one that's definitely the most well known, it's called Bash. Automate your shell commands, add &lt;code&gt;env vars&lt;/code&gt;, and increase your workflow, plus the endless of other things you can do with Bash given it's flexibility. At the crux -- Bash on more occasions than not are crucial to Travis CI builds. &lt;/p&gt;

&lt;h1&gt;
  
  
  Getting started with Bash (gh-pages example)
&lt;/h1&gt;

&lt;p&gt;Some goals you may have if you're wanting to automate processes in Bash are automating &lt;code&gt;GH_REF&lt;/code&gt; value in gpages_build.sh script with the &lt;code&gt;TRAVIS_REPO_SLUG&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In order to make the &lt;code&gt;GH_REF&lt;/code&gt; variable automatic and not have to use process load everytime, Travis CI gives us the &lt;code&gt;TRAVIS_REPO_SLUG&lt;/code&gt; which you may have seen in languages like React. The SLUG variable, which is basically the username/repo for whatever GitHub repo you're working on. You write it out like this: &lt;code&gt;GH_REF="github.com/${TRAVIS_REPO_SLUG}"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Below is an example script of just what I've explained above, we can assume this Bash script is entitled &lt;code&gt;pages.sh&lt;/code&gt;:&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="c"&gt;# This script pushes a demo-friendly version of your element and its&lt;/span&gt;
&lt;span class="c"&gt;# dependencies to gh-pages.&lt;/span&gt;

&lt;span class="c"&gt;# usage gp Polymer core-item [branch]&lt;/span&gt;
&lt;span class="c"&gt;# Run in a clean directory passing in a GitHub org and repo name&lt;/span&gt;

&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;GH_REF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"github.com/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TRAVIS_REPO_SLUG&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;org&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TRAVIS_REPO_SLUG&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; 1 &lt;span class="nt"&gt;-d&lt;/span&gt; /&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="nv"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TRAVIS_REPO_SLUG&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; 2 &lt;span class="nt"&gt;-d&lt;/span&gt; /&lt;span class="sb"&gt;`&lt;/span&gt;

&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Montana"&lt;/span&gt;
&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"montana@travis-ci.org"&lt;/span&gt;
&lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;3&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;"master"&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="c"&gt;# default to master, when branch isn't specified&lt;/span&gt;

&lt;span class="nb"&gt;mkdir &lt;/span&gt;temp &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;temp &lt;span class="c"&gt;# make temp dir &lt;/span&gt;

&lt;span class="c"&gt;# make folder (same as input, no checking!)&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nv"&gt;$repo&lt;/span&gt;
git clone &lt;span class="s2"&gt;"https://&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GH_TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GH_REF&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--single-branch&lt;/span&gt; &lt;span class="c"&gt;# you can theoretically as Montana likes to do, 'git stash pop' here&lt;/span&gt;

&lt;span class="c"&gt;# switch to gh-pages branch&lt;/span&gt;
&lt;span class="nb"&gt;pushd&lt;/span&gt; &lt;span class="nv"&gt;$repo&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null
git checkout &lt;span class="nt"&gt;--orphan&lt;/span&gt; gh-pages

&lt;span class="c"&gt;# remove all content&lt;/span&gt;
git &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# use bower to install runtime deployment&lt;/span&gt;
bower cache clean &lt;span class="nv"&gt;$repo&lt;/span&gt; &lt;span class="c"&gt;# ensure we're getting the latest from the desired branch.&lt;/span&gt;
git show &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:bower.json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; bower.json
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"{
  &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;directory&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;components&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;
}
"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .bowerrc
bower &lt;span class="nb"&gt;install
&lt;/span&gt;bower &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nv"&gt;$org&lt;/span&gt;/&lt;span class="nv"&gt;$repo&lt;/span&gt;&lt;span class="c"&gt;#$branch&lt;/span&gt;
git checkout &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; demo
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; components/&lt;span class="nv"&gt;$repo&lt;/span&gt;/demo
&lt;span class="nb"&gt;mv &lt;/span&gt;demo components/&lt;span class="nv"&gt;$repo&lt;/span&gt;/

&lt;span class="c"&gt;# redirect by default to the component folder&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;META http-equiv="&lt;/span&gt;refresh&lt;span class="s2"&gt;" content=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;0;URL=components/&lt;/span&gt;&lt;span class="nv"&gt;$repo&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;index.html

git config user.name &lt;span class="nv"&gt;$name&lt;/span&gt;
git config user.email &lt;span class="nv"&gt;$email&lt;/span&gt;

&lt;span class="c"&gt;# send it all to github&lt;/span&gt;
git add &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-am&lt;/span&gt; &lt;span class="s1"&gt;'Deploy to GitHub Pages'&lt;/span&gt;
git push &lt;span class="nt"&gt;--force&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;"https://&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GH_TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GH_REF&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; gh-pages &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1

&lt;span class="nb"&gt;popd&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementing this in your &lt;code&gt;.travis.yml&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;So below is a &lt;code&gt;travis.yml&lt;/code&gt; file I've created, and let's say you named your script &lt;code&gt;pages.sh&lt;/code&gt;, your .&lt;code&gt;travis.yml&lt;/code&gt; file would look something 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;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash&lt;/span&gt;

&lt;span class="na"&gt;sudo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt;

&lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;chmod u+x bash pages.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There you have it, you have now successfully used Bash in Travis CI. You can do something a little easier as well - just to test if you have the steps down, maybe make a Bash program just called &lt;code&gt;test.sh&lt;/code&gt; and have it read:&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="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello Travis"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then have your &lt;code&gt;.travis.yml&lt;/code&gt; file read the following:&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;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash&lt;/span&gt;

&lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;chmod u+x test.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should then see when running the build, Travis printing out &lt;code&gt;Hello Travis&lt;/code&gt;. You now know you're using Bash successfully within Travis CI.&lt;/p&gt;

</description>
      <category>news</category>
      <category>feature</category>
      <category>infrastructure</category>
      <category>community</category>
    </item>
    <item>
      <title>The Cookbook: Getting started with R</title>
      <dc:creator>Montana Mendy</dc:creator>
      <pubDate>Mon, 07 Dec 2020 10:43:22 +0000</pubDate>
      <link>https://dev.to/travisci/the-cookbook-getting-started-with-r-2hen</link>
      <guid>https://dev.to/travisci/the-cookbook-getting-started-with-r-2hen</guid>
      <description>&lt;p&gt;Some of the most downloaded R packages are built on Travis CI. In this cookbook, you'll see how easy it just is to setup Travis CI in an existing R project.&lt;/p&gt;

&lt;h1&gt;
  
  
  Getting started with R
&lt;/h1&gt;

&lt;p&gt;Let's assume you have a file called &lt;code&gt;basic_operations.R&lt;/code&gt;, and it reads something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nf"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&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="n"&gt;subtract&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nf"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&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="n"&gt;divide&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numerator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;denominator&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;denominator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Nah"&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="k"&gt;else&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="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;numerator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;denominator&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nf"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&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;h2&gt;
  
  
  Implementing Travis CI
&lt;/h2&gt;

&lt;p&gt;Now, you want to have automated testing. Thankfully there's Travis CI! Let's start off with the &lt;code&gt;.travis.yml&lt;/code&gt; file:&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;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;R&lt;/span&gt;
&lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;packages&lt;/span&gt;
&lt;span class="na"&gt;warnings_are_errors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Unit Tests
&lt;/h2&gt;

&lt;p&gt;For unit tests, we want to use something called &lt;code&gt;testthat&lt;/code&gt;. Let's say we named our whole project &lt;code&gt;sampleR&lt;/code&gt;. Your initial &lt;code&gt;testthat.R&lt;/code&gt; file would look similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testthat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sampleR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;test_check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"sampleR"&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;p&gt;In your &lt;code&gt;tests&lt;/code&gt; directory, you'll notice &lt;code&gt;/tests/testthat&lt;/code&gt; and let's say you have a file in there entitled &lt;code&gt;test-basic_operations.R&lt;/code&gt;, and it goes as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;test_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"addition works"&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="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;runif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;runif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="n"&gt;expect_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;-1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;runif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;runif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="n"&gt;expect_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&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="n"&gt;test_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"subtraction works"&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="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;runif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;runif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="n"&gt;expect_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;-1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;runif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;runif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="n"&gt;expect_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&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="n"&gt;test_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"division errors if zero"&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="n"&gt;expect_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nah"&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="n"&gt;test_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"division works"&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="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;runif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;runif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="n"&gt;expect_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;-1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;runif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;runif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="n"&gt;expect_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&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;p&gt;You can see in this unit test, we are testing if &lt;code&gt;division&lt;/code&gt;, &lt;code&gt;addition&lt;/code&gt;, and &lt;code&gt;subtraction&lt;/code&gt; passes the unit test. &lt;/p&gt;

&lt;h2&gt;
  
  
  Finishing up
&lt;/h2&gt;

&lt;p&gt;At this point, you're all set, and ready for your &lt;code&gt;R&lt;/code&gt; project to build. Last but not least, there are alternative ways to get packages when building out your &lt;code&gt;.travis.yml&lt;/code&gt;. For example if I wanted to get packages from GitHub, it would look something 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;r_github_packages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;r-lib/testthat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other alternative is to use &lt;code&gt;CRAN&lt;/code&gt;. This is how it would look grabbing your package from &lt;code&gt;CRAN&lt;/code&gt;:&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;r_packages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;testthat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Slight variants, but just different methods on getting the same package. It just comes down to your own approach and method.&lt;/p&gt;

</description>
      <category>r</category>
      <category>feature</category>
      <category>devops</category>
      <category>community</category>
    </item>
    <item>
      <title>Anchore Policy Enforcement with Travis CI </title>
      <dc:creator>Montana Mendy</dc:creator>
      <pubDate>Fri, 04 Dec 2020 14:16:00 +0000</pubDate>
      <link>https://dev.to/travisci/anchore-policy-enforcement-with-travis-ci-24ic</link>
      <guid>https://dev.to/travisci/anchore-policy-enforcement-with-travis-ci-24ic</guid>
      <description>&lt;h1&gt;
  
  
  Travis CI Pipelines: Anchore
&lt;/h1&gt;

&lt;p&gt;The Anchore Engine is an open-source project that provides a centralized service for inspection, analysis, and certification of container images. The Anchore Engine is provided as a Docker container image that can be run standalone or within an orchestration platform such as Kubernetes, Docker Swarm, Rancher, Amazon ECS, and other container orchestration platforms.&lt;/p&gt;

&lt;p&gt;Anchore Engine can be used in several ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standalone or interactively.&lt;/li&gt;
&lt;li&gt;As a service integrated with your CI/CD to bring security/compliance/best-practice enforcement to your build pipeline.&lt;/li&gt;
&lt;li&gt;As a component integrated into existing container monitoring and control frameworks via integration with its RESTful API.&lt;/li&gt;
&lt;li&gt;Policy enforcement. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementing Anchore into your project via the &lt;code&gt;.travis.yml&lt;/code&gt; file to check your containers
&lt;/h2&gt;

&lt;p&gt;First, let's take a look at your &lt;code&gt;.travis.yml&lt;/code&gt; file:&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="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;sudo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt;
&lt;span class="na"&gt;dist&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bionic&lt;/span&gt;
&lt;span class="na"&gt;notifications&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;slack&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;on_failure&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
&lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;fast_finish&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="c1"&gt;# https://github.com/anchore/anchore-engine&lt;/span&gt;
    &lt;span class="c1"&gt;# https://docs.anchore.com/current/docs/engine/quickstart/&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Scan&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;images&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Anchore&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Engine&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;docker-compose&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;wo&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;snaps&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;bionic&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;amd64"&lt;/span&gt;
      &lt;span class="na"&gt;dist&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bionic&lt;/span&gt;
      &lt;span class="na"&gt;arch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;amd64&lt;/span&gt;
      &lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker&lt;/span&gt;      
      &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see above, you're off to a good start, you have your &lt;code&gt;dist&lt;/code&gt;, &lt;code&gt;sudo&lt;/code&gt; specified, &lt;code&gt;matrix&lt;/code&gt; specified with a &lt;code&gt;job&lt;/code&gt; name. The job will be running &lt;code&gt;bionic&lt;/code&gt;, the architecture will be &lt;code&gt;amd64&lt;/code&gt; and of course Anchore is going to be checking the Docker container via &lt;code&gt;docker-compose&lt;/code&gt;, and the way this will happen is once Anchore is fetched and &lt;code&gt;docker-compose ps&lt;/code&gt; is ran, it will show the status of the container. Let's finish the &lt;code&gt;.travis.yml&lt;/code&gt; file. We'll want to start with the &lt;code&gt;before_install&lt;/code&gt; hook that Travis offers.&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;before_install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pip3 install virtualenv&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;virtualenv -p $(which python3) ~venvpy3&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;source ~venvpy3/bin/activate&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pip install -r requirements.txt&lt;/span&gt;
      &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;#  Download the docker-compose.yaml file and start&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl https://docs.anchore.com/current/docs/engine/quickstart/docker-compose.yaml &amp;gt; docker-compose.yaml&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker-compose up -d&lt;/span&gt;
        &lt;span class="c1"&gt;# Verify service availability&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker-compose ps&lt;/span&gt;
      &lt;span class="na"&gt;after_success&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deactivate&lt;/span&gt;        
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see the &lt;code&gt;script&lt;/code&gt; hook using &lt;code&gt;cURL&lt;/code&gt; to fetch Anchore, then copying the &lt;code&gt;docker-compose.yaml&lt;/code&gt; file. It then makes sure the container is up by running &lt;code&gt;docker-compose up -d&lt;/code&gt;. Now you'll want to verify service, the &lt;code&gt;.travis.yml&lt;/code&gt; file will run &lt;code&gt;docker-compose ps&lt;/code&gt;. Then of course, after it's done it will deactivate itself. This is Anchore in a simple &lt;code&gt;.travis.yml&lt;/code&gt; file. You should see the Anchore table with it's findings at the end of your build as follows: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IEM0getz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8jbkmm3fpcwlolctj9yh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IEM0getz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8jbkmm3fpcwlolctj9yh.png" alt="Anchore" width="880" height="938"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further setup
&lt;/h2&gt;

&lt;p&gt;Travis allows &lt;code&gt;docker&lt;/code&gt; command execution by default, which makes integrating Anchore Engine as simple as adding the &lt;code&gt;inline_scan&lt;/code&gt; script to your existing image build pipeline.&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;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;IMAGE_NAME="btodhunter/anchore-ci-demo" IMAGE_TAG="travisci"&lt;/span&gt;

&lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker build -t "${IMAGE_NAME}:ci" .&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl -s https://ci-tools.anchore.io/inline_scan-v0.6.0 | bash -s -- "${IMAGE_NAME}:ci"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker tag "${IMAGE_NAME}:ci" "${IMAGE_NAME}:${IMAGE_TAG}"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker push "${IMAGE_NAME}:${IMAGE_TAG}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively you can setup &lt;code&gt;cURL&lt;/code&gt; to fetch Anchore 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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl https://docs.anchore.com/current/docs/engine/quickstart/docker-compose.yaml &amp;gt; docker-compose.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Anchore Policy Enforcement
&lt;/h2&gt;

&lt;p&gt;It's fairly easy with Travis and Anchore to setup Anchore Policy Enforcement. You can setup policy enforcement with one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://ci-tools.anchore.io/inline_scan-v0.6.0 | bash &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;options] IMAGE_NAME&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the scan options Anchore offers:&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="nt"&gt;-b&lt;/span&gt;  &lt;span class="o"&gt;[&lt;/span&gt;optional] Path to &lt;span class="nb"&gt;local &lt;/span&gt;Anchore policy bundle.
&lt;span class="nt"&gt;-d&lt;/span&gt;  &lt;span class="o"&gt;[&lt;/span&gt;optional] Path to &lt;span class="nb"&gt;local &lt;/span&gt;Dockerfile.
&lt;span class="nt"&gt;-v&lt;/span&gt;  &lt;span class="o"&gt;[&lt;/span&gt;optional] Path to directory to be mounted as docker volume. All image archives &lt;span class="k"&gt;in &lt;/span&gt;directory will be scanned.
&lt;span class="nt"&gt;-f&lt;/span&gt;  &lt;span class="o"&gt;[&lt;/span&gt;optional] Exit script upon failed Anchore policy evaluation.
&lt;span class="nt"&gt;-p&lt;/span&gt;  &lt;span class="o"&gt;[&lt;/span&gt;optional] Pull remote docker images.
&lt;span class="nt"&gt;-r&lt;/span&gt;  &lt;span class="o"&gt;[&lt;/span&gt;optional] Generate analysis reports &lt;span class="k"&gt;in &lt;/span&gt;your current working directory.
&lt;span class="nt"&gt;-t&lt;/span&gt;  &lt;span class="o"&gt;[&lt;/span&gt;optional] Specify &lt;span class="nb"&gt;timeout &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;image scanning &lt;span class="k"&gt;in &lt;/span&gt;seconds &lt;span class="o"&gt;(&lt;/span&gt;defaults to 300s&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What you read above bodes well for you. With Anchore, you essentially can scan local images before pushing them into a registry, allowing you to inject scans as needed directly into your current workflows and enforce Anchore policy. You can see your policies being checked, look for the following: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fhYGUt6q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2hqs9hxzjk3haggja40b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fhYGUt6q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2hqs9hxzjk3haggja40b.png" alt="Policy" width="880" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you look above, you can see the policies being enforced, scanned, and more. I recommend looking at the &lt;code&gt;scan options&lt;/code&gt; that were laid out earlier for more verbose and customized options. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why use security scanners for containers?
&lt;/h2&gt;

&lt;p&gt;Running image scanners during continuous integration specifically scanning container images can be a cumbersome process that could be asynchronously executed during continuous integration (CI) using Travis. Including security scans in CI also allows developers to identify vulnerabilities quickly, before new software versions are released.&lt;/p&gt;

&lt;p&gt;This is why policy enforcement is crucial. Anchore is perfect for your Travis CI builds. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Sy-suV64--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cyztt8iol4xbuceffbfj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Sy-suV64--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cyztt8iol4xbuceffbfj.png" alt="Anchore" width="880" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>security</category>
      <category>feature</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>A Short Journey into Source Control Branching and Release Patterns</title>
      <dc:creator>Montana Mendy</dc:creator>
      <pubDate>Tue, 01 Dec 2020 13:54:28 +0000</pubDate>
      <link>https://dev.to/travisci/a-short-journey-into-source-control-branching-and-release-patterns-5e05</link>
      <guid>https://dev.to/travisci/a-short-journey-into-source-control-branching-and-release-patterns-5e05</guid>
      <description>&lt;p&gt;Git is a transformational technology. It’s the foundation of most of the source code management (SCM) services used today. Git’s branching, forking and merge capabilities provide developers with the freedom to work with a high degree of independence while allowing companies to control the quality of the code that makes its way into production.&lt;/p&gt;

&lt;h1&gt;
  
  
  A Short Journey into Git Branching and Release Patterns
&lt;/h1&gt;

&lt;p&gt;The process is a win-win situation for all parties involved in the software development lifecycle. A developer works within an SCM service such as &lt;a href="http://www.github.com"&gt;GitHub&lt;/a&gt;, &lt;a href="http://www.gitlab.com"&gt;GitLab&lt;/a&gt;, &lt;a href="http://www.assembla.com"&gt;Assembla&lt;/a&gt; or &lt;a href="http://www.bitbucket.com"&gt;Bitbucket&lt;/a&gt; to create a branch or fork of a repository. Then, after work is completed, the developer submits a pull request within the SCM service. The code is inspected by the project’s experts. If the code passes the project’s quality standard, it’s accepted into the project. If not, the developer is notified about how to make improvements.&lt;/p&gt;

&lt;p&gt;The process has become commonplace. Yet, for all the conformity that’s taken place around pull requests, one place where standardization is evolving is around the branching and deployment patterns a given company or project uses. There is no one set way of doing things; rather, there are a few different patterns in play. They're well worth taking a look at.&lt;/p&gt;

&lt;p&gt;The following is an analysis of the branching and release patterns used by a few open-source projects. We’ll look at some large and well-known projects — Kubernetes, Ansible and Envoy — and the Deno programming language, which is growing in popularity but small when compared to something on the order of Kubernetes.&lt;br&gt;
Understanding the different patterns is useful to those who already have or are planning to have open-source projects and need to determine a branching and release pattern to best suit their particular needs. &lt;/p&gt;

&lt;h2&gt;
  
  
  Kubernetes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://www.kubernetes.io"&gt;Kubernetes&lt;/a&gt; is a major player in the technology landscape. It’s a container orchestration system that intends to run large, distributed applications in a fail-safe, ephemeral manner. Kubernetes is designed to run big applications in a big way. &lt;/p&gt;

&lt;p&gt;Kubernetes uses a branching pattern in which all new features are created off the master branch. Work is done on the feature branch. Then, when the work is completed, a pull request is made. If approved, the code is merged from the feature branch into the master branch. When code in the master branch is determined to be ready for a version release, one of the project’s release managers will create a release branch from the master branch. (See figure 1 below.):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YbfCd8__--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/93akqagu187dk8sogddd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YbfCd8__--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/93akqagu187dk8sogddd.png" alt="Branching" width="512" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Figure 1: Kubernetes creates a branch for each major or minor release version.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, the release manager will use &lt;a href="https://github.blog/2013-07-02-release-your-software/"&gt;GitHub’s release feature&lt;/a&gt; to tag the release and create the deployment binaries. The deployment binaries are compressed into &lt;code&gt;.zip&lt;/code&gt; and &lt;code&gt;.tar.gz&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;What’s interesting about the Kubernetes approach is that creating a formal feature branch within the Kubernetes repository is a rare occurrence. Rather, a developer creates a fork of the source code from the Kubernetes repo and into their own repository. Then, when improvements in the forked code are completed, the developer creates a pull request to merge their code from the fork and into the main Kubernetes repo, as shown in figure 2 below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uXdUEDDG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f91sm0nkbtklqyvbieo0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uXdUEDDG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f91sm0nkbtklqyvbieo0.png" alt="Branching" width="512" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Figure 2: Most feature improvements in the Kubernetes project are forks that become pull requests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, not all pull requests go up against the master branch. Sometimes pull requests are made against pre-existing version branches. The Kubernetes project has a very specific way of releasing versions of code. The master branch contains the code that will be put into the next release. It is the culmination of all work done over the project’s lifespan. When that master code is deemed ready for a new version release, a new version branch is created. That branch is named according to a release-x.y naming convention — for example, &lt;code&gt;release-1.19&lt;/code&gt;. (See figure 1 above.)&lt;/p&gt;

&lt;p&gt;As mentioned above, once the version branch is created, it’s made available to the public as a .zip or .tar.gz file using GitHub’s release feature. For example, the code for version branch release-1.19 was released as &lt;a href="https://github.com/kubernetes/kubernetes/releases/tag/v1.19.0"&gt;v1.19.0&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Developers can still make backport improvements to a specific version by making a pull request against that version’s branch. (Usually, these types of changes are bug fixes.) However, when it comes time to release code that improves an existing version branch, a new version branch is not created. Rather, a new release tag is created against the existing version branch. For example, when code improvements were made that were specific to v1.19.0 of Kubernetes, the next release was &lt;a href="https://github.com/kubernetes/kubernetes/releases/tag/v1.19.1"&gt;v.1.91.1&lt;/a&gt;. This release naming pattern is consistent with the guidelines defined by the &lt;a href="https://semver.org/"&gt;semantic versioning convention&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can read the Kubernetes release policy &lt;a href="https://kubernetes.io/docs/setup/release/version-skew-policy/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Ansible
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.ansible.com/overview/how-ansible-works"&gt;Ansible&lt;/a&gt; is an environment provisioning tool. Companies use it to create computing environments such as a virtual machine (VM), and then provision that VM with an operating system, network configuration and applications.&lt;/p&gt;

&lt;p&gt;Ansible takes an approach that is somewhat similar to Kubernetes’ branching and release patterns but with a slight difference. In Ansible, the default branch is called &lt;code&gt;devel&lt;/code&gt;; in Kubernetes, the default branch is named &lt;code&gt;master&lt;/code&gt;. As with Kubernetes, Ansible will create a new branch for an intended new release. These branches are given the prefix &lt;code&gt;stable-&lt;/code&gt;, as shown in figure 3 below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UV_mqFeu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/eue1rus0imbvqfgqz1n4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UV_mqFeu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/eue1rus0imbvqfgqz1n4.png" alt="Branching" width="509" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Figure 3: The default branch in Ansible is called &lt;code&gt;devel&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Developers who want to make a contribution to the project fork the Ansible repository into their own accounts. Then, they make improvements. Then, for the most part, pull requests are made against the &lt;code&gt;devel&lt;/code&gt; branch. New features added to the &lt;code&gt;devel&lt;/code&gt; branch will appear in the next version release.&lt;/p&gt;

&lt;p&gt;Adding bug fixes is not as straightforward as adding new features. Sometimes a fix can be applied to &lt;code&gt;devel&lt;/code&gt; and then directly applied to legacy release branches. But as Ansible reports, some bug fixes made to the &lt;code&gt;devel&lt;/code&gt; branch might not cleanly rebase onto the given &lt;code&gt;stable-&lt;/code&gt; branch. As a result, there are times that code from the &lt;code&gt;devel&lt;/code&gt; branch needs to be changed a bit before it can be applied to a previous version release.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can read Ansible’s release policy &lt;a href="https://elrod.me/posts/2020-09-03-how-ansible-ansible-base-releases-work.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When it comes time to releasing code, Ansible uses &lt;a href="https://github.blog/2013-07-02-release-your-software/"&gt;GitHub’s release feature&lt;/a&gt;. When a &lt;code&gt;stable-&lt;/code&gt; branch is deemed ready for release, GitHub’s release feature is applied. This tags the &lt;code&gt;stable-&lt;/code&gt; branch with a release label and packages the deployment code into &lt;code&gt;.zip&lt;/code&gt; and &lt;code&gt;tar.gz&lt;/code&gt; files. This is very similar to the process used by Kubernetes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Envoy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.getambassador.io/learn/envoy-proxy/"&gt;Envoy&lt;/a&gt; is a popular L7 proxy and communication technology that facilitates interservice communication in distributed applications. It is an open-source project published under the sponsorship of the Cloud Native Computing Foundation.&lt;/p&gt;

&lt;p&gt;Envoy uses a branching and release pattern that is nearly identical to Kubernetes and Ansible. As with Kubernetes, the default branch is named &lt;code&gt;master&lt;/code&gt;. And, as with Kubernetes and Ansible, once code in the master branch is deemed ready for a version release, the maintainers of the Envoy project will create a branch for the particular release. They then use GitHub’s release feature to tag the release branch with the designated version number and create compressed binaries for the code for the release in &lt;code&gt;.zip&lt;/code&gt; and &lt;code&gt;.tar.gz&lt;/code&gt; formats. &lt;/p&gt;

&lt;p&gt;In terms of supporting fixes for versions of code that have already been released, Envoy release management applies security fixes directly to the master branch and then onto the release branch, adding a release tag accordingly. Should a security patch be applicable to previous, supported versions, the maintainers of the legacy branch will be notified of the available fix. Each maintainer will apply the fix to the corresponding version branch they support and to an upgrade release of that legacy branch, as shown in figure 4 below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--91bXshQ9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wk6plnijn9tjccfvcihk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--91bXshQ9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wk6plnijn9tjccfvcihk.png" alt="Branching" width="512" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Figure 4: Envoy creates release branches and then updates minor version releases against a particular release branch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The technique used for creating feature branches is also similar to the technique used by Kubernetes and Ansible. For the most part, contributors make a fork of the Envoy repository and do work on their forks. When code is ready for contribution, the developer makes a pull request to apply the code in the fork to the master branch.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can read Envoy’s release policy &lt;a href="https://github.com/envoyproxy/envoy/blob/master/RELEASES.md"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This process is nearly identical in execution to the way Kubernetes and Ansible do branching and release management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deno
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://deno.land/"&gt;Deno&lt;/a&gt; is the next-generation development language started by Ryan Dahl, the creator of Node.js. It is an open-source project.&lt;/p&gt;

&lt;p&gt;Deno developers make contributions to the project by forking the &lt;a href="https://github.com/denoland/deno"&gt;Deno repository&lt;/a&gt; into the developer’s account and then doing work on the fork. As you’ve seen, this is a very common pattern. However, unlike the large projects shown above, Deno does not create release branches from the master when it comes time to deploy code. Instead, Deno uses a simple branching and release pattern. &lt;/p&gt;

&lt;p&gt;In Deno this is only one branch, &lt;code&gt;master&lt;/code&gt;. (See figure 5 below.) There are no release branches as in the other projects described above:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--51mkokpi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8c3huttpqx57ue1c3fu6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--51mkokpi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8c3huttpqx57ue1c3fu6.png" alt="Branching" width="512" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Figure 5: Deno releases versions from a single master branch without creating release branches.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When the release managers at Deno decide a new version of code is deemed ready for release, they use GitHub’s release feature to tag the code according to a version release name, and then create the release’s &lt;code&gt;.zip&lt;/code&gt; and &lt;code&gt;.tag.gz&lt;/code&gt; binaries.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Deno does not document its release process. According to &lt;a href="https://github.com/kitsonk"&gt;Kitson Kelly&lt;/a&gt;, a frequent contributor to the Deno project, “I don't think we will write it down, as it then becomes something more difficult to change.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The simplicity of Deno’s branching and release pattern serves the project well. Deno is still a new, maturing project, and it has more flexibility in how it gets code out the door than a project that’s been around for awhile.&lt;/p&gt;

&lt;p&gt;Also, Deno has a much more limited scope of activity compared to projects such as Kubernetes, Ansible and Envoy. Thus, its “release from trunk” pattern is sustainable. While the simplicity of Deno’s branching and release pattern is effective now, it will be interesting to see how Deno’s branching and release pattern evolves as the project grows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;Creating and deploying software is a complex process. It usually involves coordinating the activities of dozens if not hundreds of developers to a productive end. Each contributor adds something special to the process. Creativity is a critical part of the software development process, and so is discipline.&lt;/p&gt;

&lt;p&gt;But, when you’re dealing with an open-source project in which contributions are made by an assortment of developers who have varying skill sets, backgrounds and interests, melding creativity and discipline together in order to make working software can be a difficult undertaking. Hence the beauty of using the pull request executed under an effective branching and release pattern. These practices allow developers to have a great deal of independence, yet provide the safeguards necessary to publish quality software on an ongoing basis.&lt;/p&gt;

&lt;p&gt;As we’ve seen in the investigations described above, branching and release patterns tend to be fairly consistent among most of the projects examined. Yet, there are differences. This is not a bad thing. All software projects are different. It’s the nature of the beast.&lt;/p&gt;

&lt;p&gt;The trick to having an effective branching and release pattern is to devise one that is consistent and easy to follow. Ease of use promotes broader adoption. An important part of “ease of use” is that the branching and release pattern must be understandable. For some projects, such as Kubernetes, Ansible and Envoy, which have a fairly complex approach, this means written documentation. For a smaller project, such as Deno, the simplicity of its branching and release pattern can be shared in an email or by word of mouth. No matter the method of communication, what all projects have in common is that branching and release are not done in an ad hoc manner. There is a pattern, and it’s followed.&lt;/p&gt;

&lt;p&gt;Having a consistent and well-known branch pattern is a key factor when intending to make working software in an effective, sustainable manner. If you’re about to start a project and have yet to establish the branching and release pattern that your team is going to use, such a discussion is worth having before you start writing code, not after.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>git</category>
      <category>infrastructure</category>
      <category>community</category>
    </item>
  </channel>
</rss>
