<?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: Iury Souza</title>
    <description>The latest articles on DEV Community by Iury Souza (@iurysza).</description>
    <link>https://dev.to/iurysza</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F58069%2Fc4aa80f2-9a44-4b67-8882-759ea18cec61.png</url>
      <title>DEV Community: Iury Souza</title>
      <link>https://dev.to/iurysza</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iurysza"/>
    <language>en</language>
    <item>
      <title>Kotlin Multiplatform under the surface</title>
      <dc:creator>Iury Souza</dc:creator>
      <pubDate>Wed, 18 Aug 2021 01:29:54 +0000</pubDate>
      <link>https://dev.to/iurysza/kotlin-multiplatform-under-the-surface-1na3</link>
      <guid>https://dev.to/iurysza/kotlin-multiplatform-under-the-surface-1na3</guid>
      <description>&lt;p&gt;The mobile development community has always had many alternatives for creating cross-platform apps. Since the days of webview-based solutions we've come a long way, but we still have many alternatives. The most recent one is the Jetbrains led, Kotlin Multiplatform Mobile project.&lt;/p&gt;

&lt;p&gt;If you're curious about how does it stand against the competition and what are its pros and cons, this brief overview may help you get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-platform vs Multiplatform
&lt;/h2&gt;

&lt;p&gt;As you may have noticed, Jetbrains calls its solution: Kotlin &lt;strong&gt;Multiplatform&lt;/strong&gt; Mobile. This might get overlooked by a lot of people, me included, up until I decided to write this down. But then it hit me: what's the difference between Cross-platform and Multiplatform?&lt;/p&gt;

&lt;p&gt;After some research, I got the answer.&lt;br&gt;
From the user's point of view, this is plain simple. In short: there's no difference.&lt;br&gt;
Multiplatform and Cross-platform implementations achieve the same thing. It simply means that the application will run on - you guessed it. Multiple platforms.&lt;/p&gt;

&lt;p&gt;Since we're focusing on mobile dev, Multiplatform means Android and iOS. But this can translate to web, desktop... whatever. Just... multiple platforms.&lt;br&gt;
It doesn't say anything about &lt;strong&gt;how&lt;/strong&gt; the app was created. If you have a code-base for an app written in Kotlin targeting android and another written in swift targeting iOS, you have a multiplatform app.&lt;/p&gt;

&lt;p&gt;Now, cross-platform is different. Cross-platform means that the same code you wrote will run on, for example, android and iOS. This is usually done via some kind of runtime that needs to be shipped to the hosting platform that enables that code to be &lt;em&gt;interpreted&lt;/em&gt; for that particular environment it is running on.&lt;/p&gt;
&lt;h2&gt;
  
  
  So what about Kotlin Multiplatform?
&lt;/h2&gt;

&lt;p&gt;The main idea behind Kotlin Multiplatform is &lt;strong&gt;code-sharing&lt;/strong&gt;. If you enter the home page, you'll see them mentioning how you can write the code once and have it running on both platforms. So -you may be asking, isn't that cross-platform... like Flutter or React? What gives?&lt;/p&gt;

&lt;p&gt;The main advantage of Kotlin Multiplatform is that it delivers &lt;strong&gt;native code&lt;/strong&gt; for multiple target platforms/architectures by taking the same code as input.&lt;br&gt;
It is able to do this because of the &lt;strong&gt;Kotlin/Native Compiler&lt;/strong&gt;, so to understand how Kotlin Multiplatform works we first need to understand what is Kotlin/Native.&lt;/p&gt;
&lt;h2&gt;
  
  
  Kotlin/Native
&lt;/h2&gt;

&lt;p&gt;Quoting from Kotlin's landing page:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Kotlin/Native is a technology for compiling Kotlin code to native binaries, which can run without a virtual machine. It is an LLVM based backend for the Kotlin compiler and a native implementation of the Kotlin standard library. &lt;/p&gt;
&lt;/blockquote&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%2Fuploads%2Farticles%2Fflnyeb40col3h8mvye69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fflnyeb40col3h8mvye69.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a lot to unpack here. Let's take the first sentence in:&lt;/p&gt;

&lt;p&gt;So Kotlin/Native will give us native binary executables that can run on an OS using no virtual machine. &lt;/p&gt;

&lt;p&gt;A binary is the machine code, ready to be run on the specified target architecture. So it's the machine code for, for example, the iOS targeting a specific CPU architecture, like &lt;code&gt;arm64&lt;/code&gt; (which is the official iPhone architecture name)&lt;/p&gt;

&lt;p&gt;Then it goes on to mention an &lt;strong&gt;LLVM based backend for the Kotlin compiler&lt;/strong&gt;. This one is dense.&lt;/p&gt;
&lt;h3&gt;
  
  
  LLVM
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://llvm.org/" rel="noopener noreferrer"&gt;The LLVM Compiler Infrastructure Project&lt;/a&gt; is probably the biggest open-source compiler project that exists to build native binaries. Languages such as C, C++, Haskell, Rust &amp;amp; Swift compile into native binaries through LLVM.&lt;/p&gt;

&lt;p&gt;Ok, fine... but what about the backend?  More specifically, what is a backend for a compiler?&lt;/p&gt;
&lt;h3&gt;
  
  
  The Kotlin Compiler, frontends, and backends
&lt;/h3&gt;

&lt;p&gt;The Kotlin compiler first compiles your Kotlin source code into an &lt;em&gt;Intermediate Representation&lt;/em&gt;, or &lt;em&gt;IR&lt;/em&gt;. This is what they call the &lt;em&gt;Frontend&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Then, the LLVM compiler takes this IR as input and generates machine code for several supported CPU architecture (like the aforementioned arm64). This is the compiler backend.&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%2Fuploads%2Farticles%2F6cgqfc6h6ryysfio80wn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6cgqfc6h6ryysfio80wn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Batteries included
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;(...) and a native implementation of the Kotlin standard library. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This last part refers to the stdlib. Kotlin multiplatform also includes a sound standard library. This allows us to get up and running with it. So when writing common code, we'll be using things like &lt;code&gt;kotlin.String&lt;/code&gt; instead of &lt;code&gt;java.lang.String&lt;/code&gt;. The &lt;em&gt;Compiler Backend&lt;/em&gt; will automatically map the IR  a &lt;code&gt;Kotlin.String&lt;/code&gt; into the correct type.&lt;/p&gt;

&lt;p&gt;If you think about it, since the native side doesn't have access to, for example, &lt;code&gt;List&lt;/code&gt;, this means you would have to roll your own when targeting that platform. Not cool.&lt;br&gt;
So the Kotlin team built this to enable us to hit the ground running when targeting native. They also did that for things like IO, networking, and more - all of which are included.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Kotlin.String   ----jvm-----&amp;gt; java.lang.String
                -----js-----&amp;gt; string
                ---native---&amp;gt; KString
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Long story short
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;The Kotlin Compiler compiles code into an Intermediate Representation with the Compiler Frontend&lt;/li&gt;
&lt;li&gt;Then, it takes this &lt;em&gt;IR&lt;/em&gt; and sends it to the LLVM based Compiler Backend.&lt;/li&gt;
&lt;li&gt;Kotlin has a stdlib that covers most basic use-cases, like IO and networking which is compiled to the appropriate target representation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Not Cross-platform, but truly Multiplatform
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Write once, run anywhere (with the jve).&lt;/em&gt;&lt;br&gt;
&lt;em&gt;-java&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Kotlin, probably:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fms3j71np9sy75jovxnrp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fms3j71np9sy75jovxnrp.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kotlin Multiplatform takes advantage of its great tooling paired with the amazing LLVM project to create true native code that you only need to write once.&lt;/p&gt;

&lt;p&gt;It is not Cross-platform because it doesn't need a runtime to be able to run anywhere. It is just plain native code.&lt;/p&gt;

&lt;p&gt;Cool, right?&lt;br&gt;
I would say that Kotlin is able to take that direction because of its tooling/architecture and the stage that LLVM project has achieved. Let's see what the future holds for this tech.&lt;br&gt;
There are certainly many challenges that we haven't discussed here, but anyways, the foundation of the tech looks pretty interesting to me.&lt;/p&gt;

&lt;p&gt;There's this &lt;a href="https://www.youtube.com/watch?v=Dul17VSiejo" rel="noopener noreferrer"&gt;talk&lt;/a&gt; from KotlinConf18 by Kevin Galligan where he goes on to make the case for this multiplatform idea and why he thinks this is &lt;em&gt;the future&lt;/em&gt;.&lt;br&gt;
I also recommend this great &lt;a href="https://blog.londogard.com/gradle/kotlin/workshop/multiplatform/2020/11/07/snake-kotlin-multiplatform.html" rel="noopener noreferrer"&gt;post&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>multiplaform</category>
      <category>mobile</category>
      <category>kmm</category>
    </item>
    <item>
      <title>A Continuous Integration approach for Kotlin projects</title>
      <dc:creator>Iury Souza</dc:creator>
      <pubDate>Sun, 24 Jan 2021 23:48:33 +0000</pubDate>
      <link>https://dev.to/iurysza/a-continuous-integration-approach-for-kotlin-4cbd</link>
      <guid>https://dev.to/iurysza/a-continuous-integration-approach-for-kotlin-4cbd</guid>
      <description>&lt;h1&gt;
  
  
  Continuous integration
&lt;/h1&gt;

&lt;p&gt;Continuous integration is one of the words that you often hear nowadays. I remember not really getting it when I first read about it. I think that most people don't get it right away. It's one of those things that you don't see the benefit before you need it, like an insurance or a sun lotion.&lt;/p&gt;

&lt;p&gt;So, let's try to tackle this one once again. What is &lt;strong&gt;Continuous Integration&lt;/strong&gt;?&lt;br&gt;
Integrate what? And why should we continually do it?&lt;/p&gt;

&lt;p&gt;As you can see, there's clearly something missing in this term: the subject. Maybe it should be called Continuous &lt;strong&gt;CODE&lt;/strong&gt; Integration, but that may not sound so appealing.&lt;br&gt;
Now you might be wondering what this &lt;em&gt;integration&lt;/em&gt; is. Here it refers to code merging. Let's jump to a full definition:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Continuous Integration (CI) is a phase in the software development cycle where code from different team members or different features are integrated together. This usually involves merging code (integration), building the application and carrying out basic tests all within an ephemeral environment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Successful Continuous integration means new code changes to an app are regularly built, tested, and merged to a shared repository. It aims to improve the quality of software, and to reduce the time taken to deliver it, by replacing the traditional practice of applying quality control after completing all development.&lt;/p&gt;

&lt;p&gt;It’s also a solution to the problem of having too many branches of an app in development at once that might conflict with each other.&lt;br&gt;
The main benefits here is making sure that the code quality doesn't decrease while keep this process small and automated.&lt;/p&gt;

&lt;p&gt;You can check my &lt;a href="https://dev.to/iurysza/series/10189"&gt;DevOps series&lt;/a&gt; articles, where I go deeper about some concepts behind CI and automation.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/iurysza" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---NI2bEvy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--TwMMO-Lb--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/58069/c4aa80f2-9a44-4b67-8882-759ea18cec61.png" alt="iurysza"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/iurysza/introduction-jg5" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;A primer&lt;/h2&gt;
      &lt;h3&gt;Iury Souza ・ Dec 17 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#automation&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/iurysza" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---NI2bEvy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--TwMMO-Lb--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/58069/c4aa80f2-9a44-4b67-8882-759ea18cec61.png" alt="iurysza"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/iurysza/part-2-automation-454g" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;The First Way&lt;/h2&gt;
      &lt;h3&gt;Iury Souza ・ Dec 17 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#automation&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#ci&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cd&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;h1&gt;
  
  
  Pipelines
&lt;/h1&gt;

&lt;p&gt;The &lt;strong&gt;pipeline&lt;/strong&gt; is another loaded term. We lend its usage from the lean manufacturing process. The basic intuition is that each software change should go through an automated code quality verification assembly line instead of using a manual, artisan like approach to review the changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uYSWhXq5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mir-s3-cdn-cf.behance.net/project_modules/disp/c0843a20257383.562e8608353ac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uYSWhXq5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mir-s3-cdn-cf.behance.net/project_modules/disp/c0843a20257383.562e8608353ac.png" alt="" width="600" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To achieve that we need a clear process to guarantee software quality after every change. &lt;br&gt;
CI pipelines can vary a lot depending on tools, type of project and many other factors, but a common flow has these steps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pushing to the code repository&lt;/li&gt;
&lt;li&gt;Running Static code analysis&lt;/li&gt;
&lt;li&gt;Unit testing&lt;/li&gt;
&lt;li&gt;Manual code revision&lt;/li&gt;
&lt;li&gt;Merge code on the main branch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7x5Mh6bS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/800/0%2AIbsu7Nvvd9gyhHxO.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7x5Mh6bS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/800/0%2AIbsu7Nvvd9gyhHxO.png" alt="" width="800" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  An android library example
&lt;/h1&gt;

&lt;p&gt;CI/CD tools can help a team automate their development, deployment, and testing. Some tools specifically handle the integration (CI) side, some manage development and deployment (CD), while others specialize in continuous testing or related functions.&lt;/p&gt;

&lt;p&gt;One of the best known open source tools for CI/CD is the automation server Jenkins. Jenkins is designed to handle anything from a simple CI server to a complete CD hub. &lt;/p&gt;

&lt;p&gt;You can even use GitHub with Jenkins, via the &lt;a href="https://github.com/jenkinsci/ghprb-plugin"&gt;ghprb-plugin&lt;/a&gt; to set up a pipeline workflow to be triggered after a Pull Request is opened.&lt;/p&gt;

&lt;p&gt;Let’s take a look at how this flow works on an android library project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Pipeline
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XQWc6oIG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dl3.pushbulletusercontent.com/aI7mb8Wt1NnUE9Dl4EWnOEldlWmWvSwK/image.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XQWc6oIG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dl3.pushbulletusercontent.com/aI7mb8Wt1NnUE9Dl4EWnOEldlWmWvSwK/image.png" alt="" width="769" height="146"&gt;&lt;/a&gt;&lt;br&gt;
This is an overview of our final pipeline. Now let's see what each &lt;em&gt;stage&lt;/em&gt; does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opening a Pull Request
&lt;/h2&gt;

&lt;p&gt;This is the starting point. Developers should open a pull request where they explain the context of ther code changes. Every project have their own pull request process and that should be clear to everybody contributing on to the code-base.&lt;br&gt;
This pull request should trigger a CI build. While that happens, other developers can contribute to the PR making questions and reviewing the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Merge
&lt;/h2&gt;

&lt;p&gt;Your integration server will then checkout the code on your branch and merge with the main branch. If there are issues here, your build will fail and that is reported directly on the PR.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static analysis
&lt;/h2&gt;

&lt;p&gt;In this pipeline this stage does two things using the same tool:&lt;/p&gt;

&lt;h4&gt;
  
  
  Code Review Automation
&lt;/h4&gt;

&lt;p&gt;To improve the code review process you can automate some parts of it. To do that you can use &lt;a href="https://danger.systems/"&gt;Danger&lt;/a&gt;. This tool "provides another logical step in your build, through this &lt;code&gt;Danger&lt;/code&gt; can help &lt;em&gt;lint&lt;/em&gt; your rote tasks in daily code review." This way you can codify your team norms. E.G.: PRs with no description or with no tests are instantly reported back directly on the PR, speeding up the review process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vv6K2vN6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://danger.systems/images/danger-screenshot-074f084c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vv6K2vN6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://danger.systems/images/danger-screenshot-074f084c.png" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Actual static analysis
&lt;/h4&gt;

&lt;p&gt;Static analysis is done on the code base of the application without the need to run the software. The goal here is to ensure the code doesn’t have bugs and conforms to standard formatting and styling. You might want to check this &lt;a href="https://dev.tolink"&gt;article&lt;/a&gt; I've written about it with my approach for Kotlin projects.&lt;/p&gt;

&lt;p&gt;Ideally, developers should have fast feedback for issues during this step, so they can start fixing them ASAP.&lt;br&gt;
To do that, I've forked the &lt;a href="https://dev.tolink"&gt;danger-checkstyle-format&lt;/a&gt; plugin and added some changes to enable reporting issues from both &lt;code&gt;ktlint&lt;/code&gt; and &lt;code&gt;detekt&lt;/code&gt; directly on the PR, making developer iteration faster.&lt;/p&gt;

&lt;p&gt;If you want to try it out you can get it here:&lt;br&gt;
 &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/iurysza"&gt;
        iurysza
      &lt;/a&gt; / &lt;a href="https://github.com/iurysza/danger-checkstyle_format"&gt;
        danger-checkstyle_format
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Report checkstyle violations to danger.systems
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
danger-checkstyle_format&lt;/h1&gt;
&lt;p&gt;Danger plugin that parses a checkstyle format file and turns it into comments on your Pull Request.&lt;/p&gt;

&lt;h2&gt;
Installation&lt;/h2&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ gem "danger-checkstyle_format", github: "iurysza/danger-checkstyle_format"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;
Checkstyle format&lt;/h2&gt;
&lt;p&gt;Many static analysis tools can create this type of file as an output
This is a typical checkstyle format file:&lt;/p&gt;
&lt;div class="highlight highlight-text-xml notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&amp;lt;?&lt;span class="pl-ent"&gt;xml&lt;/span&gt;&lt;span class="pl-e"&gt; version&lt;/span&gt;=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;1.0&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span class="pl-e"&gt; encoding&lt;/span&gt;=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;utf-8&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;?&amp;gt;
&amp;lt;&lt;span class="pl-ent"&gt;checkstyle&lt;/span&gt; &lt;span class="pl-e"&gt;version&lt;/span&gt;=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;4.3&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span class="pl-ent"&gt;file&lt;/span&gt;
        &lt;span class="pl-e"&gt;name&lt;/span&gt;=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;/Users/john-doe/project/src/main/kotlin/com/john/doe/storage/ExternalStorageService.kt&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&amp;gt;
        &amp;lt;&lt;span class="pl-ent"&gt;error&lt;/span&gt;
            &lt;span class="pl-e"&gt;column&lt;/span&gt;=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;18&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
            &lt;span class="pl-e"&gt;line&lt;/span&gt;=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;42&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
            &lt;span class="pl-e"&gt;message&lt;/span&gt;=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Caught exception is too generic. Prefer catching specific exceptions to the case that is currently handled.&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
            &lt;span class="pl-e"&gt;severity&lt;/span&gt;=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;error&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt; 
            &lt;span class="pl-e"&gt;source&lt;/span&gt;=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;detekt.TooGenericExceptionCaught&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
        /&amp;gt;
    &amp;lt;/&lt;span class="pl-ent"&gt;file&lt;/span&gt;&amp;gt;
&amp;lt;/&lt;span class="pl-ent"&gt;checkstyle&lt;/span&gt;&amp;gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This plugin will parse that file and create comments directly on your pull requests using Danger's api.
It also offers some basic configurations like:&lt;/p&gt;
&lt;h2&gt;
Run a&lt;/h2&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/iurysza/danger-checkstyle_format"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
 
&lt;h2&gt;
  
  
  Build
&lt;/h2&gt;

&lt;p&gt;In this step we use a gradle task to build our code.&lt;/p&gt;

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

&lt;p&gt;Here we run all unit tests, also with gradle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publish reports
&lt;/h2&gt;

&lt;p&gt;This step happens after the pipeline has finished. It runs &lt;a href="https://plugins.jenkins.io/jacoco/"&gt;jacoco jenkins plugin&lt;/a&gt;, a java code coverage tool to create coverage reports, then we store the test results in Jenkins. This provides a way for us to track code coverage and investigate flaky tests later on.&lt;/p&gt;

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

&lt;p&gt;You can also add some basic commands to your Jenkins pipeline, like the &lt;code&gt;rebuild&lt;/code&gt; or &lt;code&gt;rerun-tests&lt;/code&gt; commands. To help you work around flakiness on your project's build or testing stages.&lt;/p&gt;

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

&lt;p&gt;The benefits you get from having a CI pipeline in place pile up like Loan Shark interests. I strongly advise that you and your team consider creating one. If you already have one, I'd love to hear some other stages or ideas you've added to it. Please share in the comments =)&lt;/p&gt;

</description>
      <category>ci</category>
      <category>automation</category>
      <category>kotlin</category>
      <category>android</category>
    </item>
    <item>
      <title>Publishing an obfuscated kotlin library</title>
      <dc:creator>Iury Souza</dc:creator>
      <pubDate>Sun, 27 Dec 2020 03:19:56 +0000</pubDate>
      <link>https://dev.to/iurysza/publishing-an-obfuscated-kotlin-library-2kbk</link>
      <guid>https://dev.to/iurysza/publishing-an-obfuscated-kotlin-library-2kbk</guid>
      <description>&lt;p&gt;Being an android developer, I've heard about code obfuscation pretty early in my career. Since it's preconfigured in android's gradle plugin (it's actually proguard under the hood), but you don't really mess with it unless you want to.&lt;br&gt;
On the other hand, when you're developing a java/kotlin library and you want to use code obfuscation, things get a little different. In this article I wanted to give a brief overview of my strategy for publishing obfuscated kotlin libraries.&lt;/p&gt;
&lt;h1&gt;
  
  
  Code obfuscation
&lt;/h1&gt;

&lt;p&gt;If you're not sure what that means, code obfuscation is the modification of the source code to make it unintelligible, meaning it is &lt;em&gt;impossible&lt;/em&gt; for a third-party to understand.&lt;br&gt;
It's makes for a great AppSec initiative and often takes care of the bare minimum security you can have when publishing a source code out in they wild.  By making the code hard to reverse engineer, you ensure that your library's intellectual property is guarded against security threats, unauthorized access, and discovery of application vulnerabilities.&lt;/p&gt;
&lt;h1&gt;
  
  
  Proguard
&lt;/h1&gt;

&lt;p&gt;ProGuard is the most popular optimizer for Java bytecode and it also provides obfuscation for the names of classes, fields and methods.&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%2Fwww.guardsquare.com%2Ffiles%2Fmedia%2Fguardsquare2016%2FWebsite%2FProGuard%2FProGuard_build_process_b.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%2Fwww.guardsquare.com%2Ffiles%2Fmedia%2Fguardsquare2016%2FWebsite%2FProGuard%2FProGuard_build_process_b.png" alt="proguard-pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Proguard is basically a command line tool that takes input jars (aars, wars, ears, zips, apks, directories) and then performs shriking, optimization, obfuscation and preverification to output a new jar.&lt;/p&gt;

&lt;p&gt;Here we're just interested in the obfuscation step which will rename the classes, fields, and methods using short meaningless names making it really hard to read the code.&lt;/p&gt;
&lt;h1&gt;
  
  
  An obfuscation strategy
&lt;/h1&gt;
&lt;h3&gt;
  
  
  Choosing our tools
&lt;/h3&gt;

&lt;p&gt;There are probably many ways to do this, but since I have a mobile development background, we'll be doing this using proguard's gradle plugin, which will make things are little more simple, specially during the &lt;em&gt;publication&lt;/em&gt; part. Also, I'll use gradle's groovy dsl, just because I like its convenience better than kotlin's now (for gradle scripts). I may need another article to justify that, but, bear with me. This is how we integrate proguard's gradle plugin:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 groovy
buildscript {
    repositories { jcenter() }
    dependencies {
        classpath "com.guardsquare:proguard-gradle:7.0.1"
    }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;We now need to use it to obfuscate our library's &lt;code&gt;jar&lt;/code&gt;. To do that we're going to use gradle's syntax to create a task that does just that.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 groovy
task("obfuscateArtifact", type: ProGuardTask, dependsOn: jar) 


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Let's dissec the task signature for a second. Here we're declaring that this is a task of type &lt;code&gt;ProguardTask&lt;/code&gt; and that it depends on &lt;code&gt;jar&lt;/code&gt; task, meaning it has to run &lt;em&gt;after&lt;/em&gt; it. This &lt;code&gt;jar&lt;/code&gt; task comes from either the kotlin or java plugin, that you're already using and it is responsible for packaging your application artifacts into a jar file. The reason our &lt;code&gt;obfuscateArtifact&lt;/code&gt; task needs to run after this one can be seen in the image above. Proguard takes a jar file as the input, so we need this task to create the jar and then we'll apply our task on top of it.&lt;/p&gt;

&lt;p&gt;Now let's configure the input/output of our task:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 groovy
def artifactName = "$libraryArtifactId-${libraryVersion}.jar"
def obfuscatedFolder = "$buildDir/obfuscated"

injars "$buildDir/libs/$artifactName"
outjars "$obfuscatedFolder/$artifactName"


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;jar&lt;/code&gt; task will create, by default, the outputfile file in &lt;code&gt;buildDir/libs&lt;/code&gt; folder. By default, its name follows the pattern: &lt;code&gt;artifactId-version.jar&lt;/code&gt;. The &lt;code&gt;artifactId&lt;/code&gt; is defined in the publishing task that we'll see later on. It's useful to have those values as variables declared in a &lt;code&gt;gradle.properties&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Next properties are for handling deobfuscation. These are meant to be used when you want to understand your stacktraces.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 groovy
printseeds "$obfuscatedFolder/seeds.txt"
printmapping "$obfuscatedFolder/mapping.txt"


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Handling dependencies
&lt;/h3&gt;

&lt;p&gt;After that, we have to make proguard understand our project's dependencies. To do that we need to provide it with java's standard library and ours runtime, and compile-time  dependencies. A quick explanation of the last two:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;compile-time&lt;/code&gt; classpath contains the classes that you’ve added in order to compile your code. This is the equivalent of the classpath passed to &lt;code&gt;javac&lt;/code&gt; (or any other java compiler).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;runtime:&lt;/code&gt; classpath contains the classes that are used when your application is running. That’s the classpath passed to the &lt;code&gt;java&lt;/code&gt; executable. This is all the code your library is using when it's running.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In proguard we can use the &lt;code&gt;libraryjars&lt;/code&gt; property to provide these dependencies:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 groovy
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
libraryjars configurations.runtime
libraryjars sourceSets.main.compileClasspath


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The first line has a path pointing to a &lt;code&gt;rt.jar&lt;/code&gt;. This stands for &lt;code&gt;runtime JAR&lt;/code&gt; and it has all the classes from the Core Java API. This is the path you use when you're targeting java 8 and below. The other two lines handles runtime and compile-time dependencies that we get by using gradle's dsl.&lt;/p&gt;
&lt;h3&gt;
  
  
  Wrapping up
&lt;/h3&gt;

&lt;p&gt;The last piece of this puzzle is proguard's configuration file. I prefer doing that in a separated file. If you're using intelij you can get nice syntax highlight for this file, which in my book is always a nice to have.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 groovy
configuration files("$projectDir/gradle/configuration.pro")


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The configuration you're going to use is up to you, even if you don't add anything in the config file, proguard will handle code obfuscation by default. We'll come back to this file again.&lt;/p&gt;

&lt;p&gt;Ok, now if you want to obfuscate your code you just need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;run &lt;code&gt;jar&lt;/code&gt; task&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;obfuscateArtifact&lt;/code&gt; task&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Problem solved! Or maybe not.&lt;/p&gt;
&lt;h1&gt;
  
  
  Automating the publication pipeline
&lt;/h1&gt;

&lt;p&gt;Assuming you get the &lt;code&gt;artifactId&lt;/code&gt; right, what we did until now may actually work for youu. The obfuscate task will trigger a build and then obfuscate the jar. But that's not ideal. We don't want to manually run this specific task every time. To me, the obfuscation step should be just a part of our library's publication pipeline now. We shouldn't have to remember about it anymore. In order to fix this we need to take a look at this so called, publication pipeline.&lt;/p&gt;

&lt;p&gt;If you already have one, it may be just a simple &lt;code&gt;publishing&lt;/code&gt; task, something like this:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 groovy
group = "com.myLibrary.group."
version = "$myLibraryVersion"

publishing {
    publications {
        create(MavenPublication) {
            artifactId = "$myLibraryArtifactId"
            from components["java"]
            name = "My Library's name"
            description = "My Library's description"
        }
    }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The key here is the &lt;code&gt;from components["java"]&lt;/code&gt; declaration. Quoting from gradle's docs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Components are defined by plugins and provide a simple way to define a publication for publishing. They comprise one or more artifacts as well as the appropriate metadata. For example, &lt;strong&gt;the java component consists of the production JAR — produced by the jar task — and its dependency information&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, this is how our publication task gets the project's artifacts and dependencies. Therefore, if we want to publish an obfuscated library we need to remove that line and provide our publication with the output produced by &lt;code&gt;obfuscateArtifact&lt;/code&gt; task.&lt;/p&gt;

&lt;p&gt;So, how can we do that? &lt;br&gt;
As we saw in the documentation the &lt;code&gt;components["java"]&lt;/code&gt; is automatically defined by the java/kotlin plugin and includes all classes from the default &lt;code&gt;sourceSets&lt;/code&gt;. If we want to define our own artifacts that we want to be published, we can use the &lt;code&gt;artifact&lt;/code&gt; property.&lt;br&gt;
This is how you do it, inside the &lt;code&gt;create&lt;/code&gt; block, add:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 groovy
artifact("$buildDir/obfuscated/${libraryArtifactId}-${version}.jar") {
    builtBy obfuscateArtifact
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Now, let's read this backwards: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;builtBy&lt;/code&gt; tells which task is going to build the artifact &lt;/li&gt;
&lt;li&gt;the argument to the &lt;code&gt;artifact&lt;/code&gt; function is the path where this task is going to output it. This path was defined earlier by the &lt;code&gt;outputJar&lt;/code&gt; property, in our &lt;code&gt;obfuscateArtifact&lt;/code&gt; task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Almost there! Now, we need to provide the dependency information. This comes automatically when using the &lt;code&gt;components["java"&lt;/code&gt;, but here we need to manually provide it. Still in the &lt;code&gt;create&lt;/code&gt; block, add:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 groovy 
pom.withXml {
    def dependencies = asNode().appendNode("dependencies")
    configurations.implementation.allDependencies.each { dep -&amp;gt;
        def depNode = dependencies.appendNode("dependency")
        depNode.appendNode("groupId", dep.group)
        depNode.appendNode("artifactId", dep.name)
        depNode.appendNode("version", dep.version)
    }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;And that's about it!&lt;br&gt;
Now, we can forget about obfuscation. We just run the publish task and get our obfuscated code published seamlessly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Naming conflicts
&lt;/h2&gt;

&lt;p&gt;If you're using this library in another codebase that will also obfuscate its code you might get some naming conflicts due to proguard using the same name for classes/methods in that projects own obfuscation process. To fix this you can provide proguard with a custom dictionary.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 txt
//class-dictionary.txt
Lorem
ipsum
dolor
sit
amet
consectetur
adipiscing
...


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;You'll then need tell proguard about it in the &lt;code&gt;configuration.pro&lt;/code&gt; file, by adding the line.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 pro
-classobfuscationdictionary class-dictionary.txt


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Now, proguard will use the words in that file to name our classes during the obfuscation step, avoiding naming conflicts.&lt;/p&gt;

&lt;p&gt;The last thing I like to do is to create a different &lt;code&gt;artifactId&lt;/code&gt; for the unobfuscated version of the library and to publish both versions. You can see the complete script bellow:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This diagram shows our end product.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fchii8hfae2o4in2y0fw9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fchii8hfae2o4in2y0fw9.png" alt="diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.guardsquare.com/en/products/proguard" rel="noopener noreferrer"&gt;Proguard home page&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.appsealing.com/code-obfuscation-comprehensive-guide/" rel="noopener noreferrer"&gt;Code obfuscation guide&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>java</category>
      <category>appsec</category>
      <category>gradle</category>
    </item>
    <item>
      <title>Continuous Kotlin Static Analysis</title>
      <dc:creator>Iury Souza</dc:creator>
      <pubDate>Sun, 20 Dec 2020 20:45:00 +0000</pubDate>
      <link>https://dev.to/iurysza/continuous-kotlin-static-analysis-2l2o</link>
      <guid>https://dev.to/iurysza/continuous-kotlin-static-analysis-2l2o</guid>
      <description>&lt;p&gt;Static analysis is one of those terms that people toss around that usually scares junior devs, (it certainly scared me) but it's a simple and powerful tool to have under your belt. &lt;br&gt;
In this article I wanted to give a brief overview about its definition, best practices and common pitfalls. In the end I'll provide a solution that's been working for me.&lt;/p&gt;
&lt;h1&gt;
  
  
  What is it anyway?
&lt;/h1&gt;

&lt;p&gt;Static analysis is a way to find errors and other issues in a source code without actually executing it (hence, static). The process provides an understanding of the code structure and can help ensure that the code adheres to industry standards and capture issues early.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In sum, it's a glorified spellchecker. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is not a new idea, the first one of these tools is &lt;a href="https://www.wikiwand.com/en/Lint_(software)" rel="noopener noreferrer"&gt;lint&lt;/a&gt; which dates back from the late 70's and is the most common kind of static analysis tool. Most languages have a &lt;em&gt;linter&lt;/em&gt; nowadays. &lt;br&gt;
The automation provided by these tools is fundamental to improve code quality, as it greatly increase code reviewing speed while also being less prone to human error.&lt;/p&gt;
&lt;h4&gt;
  
  
  Let machines do what they're best at!
&lt;/h4&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%2Fthumbs.gfycat.com%2FAchingOptimisticAlabamamapturtle-size_restricted.gif" 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%2Fthumbs.gfycat.com%2FAchingOptimisticAlabamamapturtle-size_restricted.gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  What can it do?
&lt;/h3&gt;

&lt;p&gt;Static analysis can be broken into formal, cosmetic, design properties, error checking and predictive categories. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Formal&lt;/strong&gt;  checks if the code is correct; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cosmetic&lt;/strong&gt; checks if the code syncs up with style standards; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design properties&lt;/strong&gt; check the level of complexities; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error checking&lt;/strong&gt; looks for code violations; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Predictive&lt;/strong&gt; guesses how code will behave when run.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  But who needs this anyway?
&lt;/h1&gt;

&lt;p&gt;In short, everyone does. Quoting John Carmack, lead developer of Wolfenstein, Doom, Quake and their sequels:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The first step is fully admitting that the code you write is riddled with errors. That is a bitter pill to swallow for a lot of people, but without it, most suggestions for change will be viewed with irritation or outright hostility. You have to want criticism of your code.&lt;/p&gt;

&lt;p&gt;Automation is necessary. It is common to take a sort of smug satisfaction in reports of colossal failures of automatic systems, but for every failure of automation, the failures of humans are legion. Exhortations to "write better code" plans for more code reviews, pair programming, and so on just don't cut it, especially in an environment with dozens of programmers under a lot of time pressure. The value in catching even the small subset of errors that are tractable to static analysis every single time is huge.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;
  
  
  Your first Quality Gate
&lt;/h1&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%2Fstatic.wikia.nocookie.net%2Fageofempires%2Fimages%2Fe%2Fe0%2FPalisadegate.png%2Frevision%2Flatest%2Ftop-crop%2Fwidth%2F450%2Fheight%2F450%3Fcb%3D20170112132848" 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%2Fstatic.wikia.nocookie.net%2Fageofempires%2Fimages%2Fe%2Fe0%2FPalisadegate.png%2Frevision%2Flatest%2Ftop-crop%2Fwidth%2F450%2Fheight%2F450%3Fcb%3D20170112132848"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Static code analysis is a common DevOps practice and makes for a great first quality gate, since it provides early feedback for developers making it easier to fix issues.&lt;br&gt;
So, if you've reached this far, I'm hoping that I was able to convince you, but how can we get static analysis added to your project?&lt;/p&gt;
&lt;h1&gt;
  
  
  Kotlin static analysis landscape
&lt;/h1&gt;

&lt;p&gt;So, in the Kotlin community two tools usually come up when talking about static analysis: &lt;a href="https://github.com/pinterest/ktlint" rel="noopener noreferrer"&gt;ktlint&lt;/a&gt; and &lt;a href="https://github.com/detekt/detekt" rel="noopener noreferrer"&gt;detekt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ktlint&lt;/code&gt; prides itself for taking a &lt;em&gt;no-configuration&lt;/em&gt; approach to linting. The idea is that it will always reflect kotlin's &lt;a href="https://kotlinlang.org/docs/reference/coding-conventions.html" rel="noopener noreferrer"&gt;official code style&lt;/a&gt; so the idea here is to be a cosmetic static analysis tool. &lt;br&gt;
&lt;code&gt;Detekt&lt;/code&gt; on the other hand provides many other features like complexity reports, code smell analysis while also being extensively configurable.&lt;/p&gt;
&lt;h1&gt;
  
  
  Basic integration pitfalls
&lt;/h1&gt;

&lt;p&gt;Both tools provide many ways to integrate in your project. You can add a plain gradle task, a gradle plugin or install the command line interface. The recommended route is via a gradle plugin.&lt;br&gt;
After integrating these tools in your project you can use tasks like &lt;code&gt;detektCheck&lt;/code&gt; and &lt;code&gt;ktlintCheck&lt;/code&gt; to run over all your project and report the issues. And that's it, you're done!&lt;/p&gt;
&lt;h5&gt;
  
  
  Yes, but also no.
&lt;/h5&gt;

&lt;p&gt;The problem with the basic integration is that in real life things tend to be a little different.&lt;br&gt;
If you're adding static analysis to a greenfield project, it's usually fine to run those tasks over the whole project, but if that is not your case, you'll probably want to avoid auto-formatting your whole project or getting 5k+ warnings every time you run one of those tasks. Warnings just turn into noise. &lt;br&gt;
You could use a &lt;em&gt;baseline&lt;/em&gt;, which is a configuration that helps incremental adoption on a project, but you're still going to stumble in some issues related to running these over your whole codebase.&lt;/p&gt;
&lt;h2&gt;
  
  
  A better solution
&lt;/h2&gt;

&lt;p&gt;If you stop and think about it to be able to get the benefits I've mentioned in the beginning of this post, ideally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You want these tasks to run fast, so you can run them often.&lt;/li&gt;
&lt;li&gt;You want to incrementally adopt this in your codebase&lt;/li&gt;
&lt;li&gt;And last, but certainly not least: you don't want to keep forgetting to run these tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Configuring both tools is really similar, so I'll highlight some points that happen in both scripts. You can get detekt's &lt;a href="https://gist.github.com/iurysza/005c08ff7f1892097c2823b1786ac087" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, the magic here is to get the files that were changed in our commit &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There's git command that does just that:
&lt;code&gt;$ git diff --name-only origin/main --relative&lt;/code&gt; In line 38 we call it by using groovy's api. This will output all the change files names.&lt;/li&gt;
&lt;li&gt;In line 44 we process the output so that we can pass the filename list to ktlint/detekt.&lt;/li&gt;
&lt;li&gt;From lines 13 to 20 we decide whether we need to run static analysis or just ignore all files.&lt;/li&gt;
&lt;/ul&gt;


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


&lt;p&gt;And that's about it! The rest of the code (from both scripts) just handles the report output location.&lt;/p&gt;

&lt;h4&gt;
  
  
  Good! Almost there now!
&lt;/h4&gt;

&lt;p&gt;We just need a way to make this a part of our workflow. This way we won't forget to run these tasks. And yeah, we can use a &lt;code&gt;git-hook&lt;/code&gt; like the &lt;code&gt;pre-commit&lt;/code&gt; hook to do just that.&lt;/p&gt;

&lt;p&gt;If you're not familiar with git-hooks, you can check them &lt;a href="https://www.atlassian.com/git/tutorials/git-hooks" rel="noopener noreferrer"&gt;here&lt;/a&gt;, but if you want to keep reading, just think about them as a piece of code that is going to be called when you do something in git.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;pre-commit&lt;/code&gt; hook will run when you try to commit something. It runs before git actually creates the commit, so the idea is to only allow a new commit when our static analysis passes successfully, effectively creating our first quality gate. Woot woot!&lt;/p&gt;


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


&lt;p&gt;&lt;a href="https://i.giphy.com/media/IwAZ6dvvvaTtdI8SD5/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/IwAZ6dvvvaTtdI8SD5/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it! This makes sure that every piece of code you commit has to follow the minimum quality standards that you and your team agreed upon.&lt;br&gt;
This is not yet a &lt;em&gt;final solution&lt;/em&gt; as people can bypass those checks by running &lt;code&gt;git commit --no-verify&lt;/code&gt;, but it's a solid first step towards a better codebase.&lt;/p&gt;

&lt;p&gt;Besides, if you think about it, these scripts can be easily integrated to a CI environment. Wouldn't it be nice if it could send those warnings as inline comments in your pull request? Stay tuned for more =)&lt;/p&gt;

&lt;h4&gt;
  
  
  References
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.gamasutra.com/view/news/128836/InDepth_Static_Code_Analysis.php" rel="noopener noreferrer"&gt;Carmac's blog&lt;/a&gt;&lt;br&gt;
&lt;a href="https://searchsoftwarequality.techtarget.com/definition/static-analysis-static-code-analysis" rel="noopener noreferrer"&gt;Static analysis definition&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>mobile</category>
      <category>codequality</category>
      <category>devops</category>
    </item>
    <item>
      <title>The First Way</title>
      <dc:creator>Iury Souza</dc:creator>
      <pubDate>Thu, 17 Dec 2020 11:50:12 +0000</pubDate>
      <link>https://dev.to/iurysza/part-2-automation-454g</link>
      <guid>https://dev.to/iurysza/part-2-automation-454g</guid>
      <description>&lt;p&gt;The idea behind the First Way is that by identifying, measuring, and improving the flow of work through our value stream, we can optimize and refine the ability to deliver value to our customers.&lt;/p&gt;

&lt;p&gt;The first step towards that is to split every piece of work in the value stream and automate it. This is often called a pipeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7fKzmX0B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://digitize01.com/image/image_lib/images/CI-CD-Pipeline.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7fKzmX0B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://digitize01.com/image/image_lib/images/CI-CD-Pipeline.png" alt="pipeline" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The foundation of our pipelines
&lt;/h1&gt;

&lt;p&gt;You're probably already using a build system to automate some parts of our value stream, but we can do better. Quoting from the Devops Handbook:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In order to create fast and reliable flow from Dev to Ops, we must ensure that we always use &lt;strong&gt;production-like environments&lt;/strong&gt; at every stage of the value stream. Furthermore, these environments must be created in an &lt;strong&gt;automated manner&lt;/strong&gt;, ideally on demand from &lt;strong&gt;scripts&lt;/strong&gt; and configuration information &lt;strong&gt;stored&lt;/strong&gt; in &lt;strong&gt;version control&lt;/strong&gt;, and entirely self-serviced, without any manual work required from Operations. Our goal is to ensure that we can &lt;strong&gt;re-create&lt;/strong&gt; the entire production environment based on what’s in version control.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The authors go on to say that we should enable on demand creation of dev, test, and production environments so developers can run production-like environments anywhere, even on their own computers, created on demand and self-serviced.&lt;/p&gt;

&lt;p&gt;This way, developers can run and test their code in a production-like environment as part of their daily work, &lt;br&gt;
providing early and constant feedback on code quality.&lt;/p&gt;

&lt;p&gt;We've all been there before:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nzNS1uUa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://4.bp.blogspot.com/_CywCAU4HORs/S-HYtX4vOkI/AAAAAAAAAHw/Hzi5PYZOkrg/s1600/ItWorksOnMyMachine.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nzNS1uUa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://4.bp.blogspot.com/_CywCAU4HORs/S-HYtX4vOkI/AAAAAAAAAHw/Hzi5PYZOkrg/s1600/ItWorksOnMyMachine.jpg" alt="it works on my machine" width="728" height="610"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The "It works on my machine!" issue comes from the fact that in any complex system there's just too many variables to manage. If you google &lt;em&gt;The Matrix of Hell&lt;/em&gt; you'll might see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Stw1D6To--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://files.speakerdeck.com/presentations/c5ce6ce091ee01319fc1623dfa5ee5e7/slide_6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Stw1D6To--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://files.speakerdeck.com/presentations/c5ce6ce091ee01319fc1623dfa5ee5e7/slide_6.jpg" alt="Matrix from hell" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Different kind of applications will have different rows and columns in this table, but you get the idea: - Multiple environments with multiple third party dependencies, create a combinatorial explosion that no sane human being can manage.&lt;/p&gt;

&lt;p&gt;Most companies will have a test and production environments, maybe you even have a dev environment where you can safely run your app with the hottest new features. But as the project evolves, non-production environments tend to degrade. It's hard for them to keep up with prod because of lack of automation or the discipline of constantly updating it. After a while the dev environment will have so many small things that work differently that it becomes hard to trust it. Some months down the line and people will stop believing anything that happens in the dev environment and only newcomers, still unaware of these issues, will be using it at all.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to fix that?
&lt;/h1&gt;

&lt;p&gt;The issue is that if these environments were manually created, you can't expect people to maintain them equally.&lt;br&gt;
By automating their creation we enable anyone to quickly spin up a new environment on demand, enabling every developer to have their own local environment when they need one. &lt;br&gt;
The automation scripts will make sure that the correct configuration is loaded on each environment, avoiding hundreds or thousands of hours of unneeded headaches over a misconfiguration due to human error.&lt;/p&gt;

&lt;p&gt;This way we're effectively giving the development team access to production-like environments by treating your infrastructure and configuration as code, making immutable infrastructure, ensuring where we operate, develop, and test is comparable and a reliable indicator of system operation for customers — such that new value contributed by developers can easily and predictably be deployed to customers.&lt;/p&gt;

&lt;h1&gt;
  
  
  It's hard, but it pays in the long run!
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e1OavHv6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgs.xkcd.com/comics/the_general_problem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e1OavHv6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgs.xkcd.com/comics/the_general_problem.png" alt="xkcd" width="550" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is not a simple issue to solve. And you should be mindful about when and where to start the process.&lt;/p&gt;

&lt;p&gt;In my experience, small startups or software studios tend to overlook this, because it's too much to worry about this stuff at their product stage. &lt;/p&gt;

&lt;p&gt;If your project doesn't have to scale, fine. You can get away from following these ideas in smaller projects, but the engineering team has to stay vigilant for when they should stop and implement a solution.&lt;/p&gt;

&lt;p&gt;If you get big enough the cost of not having on-demand, dev/prod environment parity will also scale, even faster than your product. And hiring more people will only make the cost increase.&lt;br&gt;
Hundreds or thousands of development hours go down the drain because of this issue. Bugs that are impossible to reproduce make debugging even harder, fear of changing "buggy" parts of the application causes code quality to suffer and everybody suffers.&lt;/p&gt;

&lt;p&gt;Every team and organization is different and deciding when to start with this approach has to made in case by case scenario, but I'd argue that it's certainly cost-effective to gradually implement this idea in the early stages of a project.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create our single repository of truth for the entire system
&lt;/h4&gt;

&lt;p&gt;To ensure that we can restore production service repeatedly and predictably (and, ideally, quickly) even when catastrophic events occur, we must check in all the assets needed to recreate the system state.&lt;/p&gt;

&lt;p&gt;That includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All application code and dependencies (e.g., libraries, static content, etc.)&lt;/li&gt;
&lt;li&gt;Any script used to create database schemas, application reference data, etc.&lt;/li&gt;
&lt;li&gt;All the environment creation tools and artifacts&lt;/li&gt;
&lt;li&gt;Any file used to create containers (e.g., Docker or composition files)&lt;/li&gt;
&lt;li&gt;All supporting automated tests and any manual test scripts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ideally this should happen using immutable infrastructure where no manual changes occur - make it easier to destroy &lt;br&gt;
and rebuild than to configure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encoding knowledge&lt;/strong&gt; and &lt;strong&gt;sharing&lt;/strong&gt; it through a repository is one of the powerful mechanism for propagating knowledge.&lt;br&gt;
Particularly when it includes every library (internal or external), and those each have an owner responsible for ensuring it successfully passes all tests.&lt;/p&gt;

&lt;h1&gt;
  
  
  Wrapping up
&lt;/h1&gt;

&lt;p&gt;We've seen how dev/prod parity begets automation. If you're not yet embracing these concepts, well, you quite frankly should, or at least be aware of the issues that are coming your way. &lt;br&gt;
But fret not! We've all been there and those who came out alive have some very interesting ideas about how to solve it. We just have to listen to them.&lt;/p&gt;

&lt;p&gt;Coming up next: Test automation! Stay tuned.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>automation</category>
      <category>ci</category>
      <category>cd</category>
    </item>
    <item>
      <title>A primer</title>
      <dc:creator>Iury Souza</dc:creator>
      <pubDate>Thu, 17 Dec 2020 00:16:22 +0000</pubDate>
      <link>https://dev.to/iurysza/introduction-jg5</link>
      <guid>https://dev.to/iurysza/introduction-jg5</guid>
      <description>&lt;p&gt;Recently, I've been trying to improve my understanding of good CI and CD practices and I often saw this word: &lt;code&gt;DevOps&lt;/code&gt;.&lt;br&gt;
I mean, I thought I sort of understood what DevOps meant: - The team who keeps our infrastructure up and running and that manages some crazy scripts for on our pipelines, right?  Well... no.&lt;/p&gt;

&lt;p&gt;So I decided to take some time to understand this. Picked a book on the subject, read some articles here and there... &lt;br&gt;
And in this series I'll try to talk about some of what I learned and about my own experiences.&lt;/p&gt;

&lt;p&gt;The book I picked up was &lt;em&gt;The DevOps Handbook&lt;/em&gt;, subtitled: &lt;em&gt;How to Create World-Class Agility, Reliability, &amp;amp; Security in Technology Organizations&lt;/em&gt;. This is an incredible source of knowledge, written by some very smart folks from the DevOps community. After that, one thing led to another, and I stumbled upon &lt;em&gt;The Twelve-Factor App&lt;/em&gt;. This one is a methodology developed by people working for the Heroku platform. They provide key insights for anyone that develops software delivered as a service (SaaS), but a lot of what they talk about is useful for any kind of software. You should really check them out if you have the chance. But enough with that. Let's dive in.&lt;/p&gt;

&lt;h1&gt;
  
  
  So, what is DevOps?
&lt;/h1&gt;

&lt;p&gt;Quoting Wikipedia:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DevOps is a set of practices that combines software development and IT operations.&lt;br&gt;
It aims to shorten the systems development life cycle and provide continuous delivery with high software quality.&lt;br&gt;
DevOps is complementary with Agile software development; several DevOps aspects came from Agile methodology.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, this is basically agile at a macro-level. When you take a birds-eye view of all the agile methodologies,&lt;br&gt;
clean-code best practices, conventions, collaboration tools, etc, what you and your organization really &lt;br&gt;
want is to deliver value to the costumer. Ok, makes sense, right?&lt;/p&gt;

&lt;p&gt;It does! And the people from the &lt;em&gt;DevOps Handbook&lt;/em&gt; even came up with this idea of a &lt;code&gt;value-stream&lt;/code&gt;. Now, what is a value stream is in the first place?&lt;/p&gt;

&lt;p&gt;Quoting from the book: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In the DevOps, we typically define a value stream as the process required to &lt;strong&gt;convert a business hypothesis&lt;/strong&gt; into a &lt;strong&gt;technology-enabled service&lt;/strong&gt; that delivers &lt;strong&gt;value&lt;/strong&gt; to the &lt;strong&gt;customer&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y7p9dsc_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/zlf5jsfw0qu2hv513xa7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y7p9dsc_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/zlf5jsfw0qu2hv513xa7.png" alt="Value Stream" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The Three Ways
&lt;/h1&gt;

&lt;p&gt;Right off the bat, the authors split DevOps practices into three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The First Way&lt;/strong&gt; enables fast left-to-right flow of work from Development to Operations to the customer. In order to maximize flow, we need to make work visible, reduce our batch sizes and intervals of work, build in quality by preventing defects from being passed to downstream work centers, and constantly optimize for the global goals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Second Way&lt;/strong&gt; enables the fast and constant flow of feedback from right to left at all stages of our value stream. It requires that we amplify feedback to prevent problems from happening again, or enable faster detection and recovery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Third Way&lt;/strong&gt; enables the creation of a generative, high-trust culture that supports a dynamic, disciplined, and scientific approach to experimentation and risk-taking, facilitating the creation of organizational learning, both from our successes and failures. Furthermore, by continually shortening and amplifying our feedback loops, we create ever-safer systems of work and are better able to take risks and perform experiments that help us learn faster than our competition and win in the marketplace.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The book is divided into three parts, one per way. Each part documents the relevant technical practices with supporting case studies and experiences sourced from industry behemoths like Netflix and Amazon.&lt;/p&gt;

&lt;p&gt;But this is not a book review, and for the purpose of this series I wanted to share some insights on topics I've found particularly compelling. Let's dive in!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>automation</category>
    </item>
    <item>
      <title>Setting up MockServer</title>
      <dc:creator>Iury Souza</dc:creator>
      <pubDate>Sat, 07 Nov 2020 18:41:01 +0000</pubDate>
      <link>https://dev.to/iurysza/setting-up-mockserver-3kbe</link>
      <guid>https://dev.to/iurysza/setting-up-mockserver-3kbe</guid>
      <description>&lt;h2&gt;
  
  
  Main goals:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Simple and declarative testing environment setup.&lt;/li&gt;
&lt;li&gt;Runs everywhere&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Strategy
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Set up a replicable local server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker - &lt;em&gt;Containerized applications (actually write once, runs anywhere)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provide an expectations json where all the requests are mapped out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MockServer - Creates a local server with complex request/response expectations through a json resource or a REST API. &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%2Fuploads%2Farticles%2Fklxbj4i1k3k9gpgxufsm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fklxbj4i1k3k9gpgxufsm.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it happen
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.docker.com/get-docker/" rel="noopener noreferrer"&gt;Install Docker&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install &lt;a href="https://docs.docker.com/compose/install/" rel="noopener noreferrer"&gt;Docker Compose&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure your docker daemon is up and running.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a folder for your MockServer setup.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

  &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /path/to/mockserver_container/ &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/mockserver_container


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Create the &lt;code&gt;docker-compose.yml&lt;/code&gt; .&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is where you'll setup your container for MockServer. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

  &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; ./docker-compose.yml &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; vim ./docker-compose.yml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Paste this code snippet:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2.4"&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mockServer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mockserver/mockserver:latest&lt;/span&gt;
      &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;1080:1080&lt;/span&gt;
      &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;MOCKSERVER_WATCH_INITIALIZATION_JSON&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
        &lt;span class="na"&gt;MOCKSERVER_PROPERTY_FILE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/config/mockserver.properties&lt;/span&gt;
        &lt;span class="na"&gt;MOCKSERVER_INITIALIZATION_JSON_PATH&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/config/initializerJson.json&lt;/span&gt;
      &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bind&lt;/span&gt;
          &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/config&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is saying:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a service named &lt;code&gt;mockserver&lt;/code&gt; using the docker image from &lt;code&gt;mockserver/mockserver:latest&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assign the &lt;code&gt;host port&lt;/code&gt; 1080 to the &lt;code&gt;container port&lt;/code&gt; 1080.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set the &lt;code&gt;enviroment variables&lt;/code&gt; to the provided paths.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;code&gt;volume&lt;/code&gt; binding from the &lt;code&gt;current directory&lt;/code&gt; (this file's dir) to &lt;code&gt;/config&lt;/code&gt; inside the container.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup the Expectation Initializer JSON.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Create the &lt;code&gt;initializerJson&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

  &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; ./initializerJson.json &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; vim ./initializerJson.json


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Paste this code snippet:&lt;/li&gt;
&lt;/ul&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="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;"httpRequest"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/api/v1/weather"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"queryStringParameters"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"code"&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="s2"&gt;"10969"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"httpResponse"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;wheather&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: 20.5}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;



&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Full documentation reference can be found &lt;a href="https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.9.x#/Expectation" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Running your container
&lt;/h2&gt;

&lt;p&gt;Now that we've got the plumbing out of the way, it's time to run it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inside the folder you created the &lt;code&gt;.yml&lt;/code&gt; type:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

  &lt;span class="nv"&gt;$ &lt;/span&gt;docker-compose up


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Your terminal should print something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

  Creating mockserver_mockServer_1 ... &lt;span class="k"&gt;done
  &lt;/span&gt;Attaching to mockserver_mockServer_1
  mockServer_1  | 
  mockServer_1  | java  &lt;span class="nt"&gt;-Dfile&lt;/span&gt;.encoding&lt;span class="o"&gt;=&lt;/span&gt;UTF-8 &lt;span class="nt"&gt;-jar&lt;/span&gt; /opt/mockserver/mockserver-netty-jar-with-dependencies.jar  &lt;span class="nt"&gt;-server&lt;/span&gt;
  mockServer_1  | 
  mockServer_1  | 2020-04-11 15:52:30  org.mockserver.log.MockServerEventLog  INFO  creating expectation:
  mockServer_1  | 
  mockServer_1  |   &lt;span class="o"&gt;{&lt;/span&gt;
  mockServer_1  |     &lt;span class="s2"&gt;"id"&lt;/span&gt; : &lt;span class="s2"&gt;"3f3962d2-9c03-4dce-95cd-2522962ceccb"&lt;/span&gt;,
  mockServer_1  |     &lt;span class="s2"&gt;"priority"&lt;/span&gt; : 0,
  mockServer_1  |     &lt;span class="s2"&gt;"httpRequest"&lt;/span&gt; : &lt;span class="o"&gt;{&lt;/span&gt;
  mockServer_1  |       &lt;span class="s2"&gt;"method"&lt;/span&gt; : &lt;span class="s2"&gt;"GET"&lt;/span&gt;,
  mockServer_1  |       &lt;span class="s2"&gt;"path"&lt;/span&gt; : &lt;span class="s2"&gt;"/api/v1/weather"&lt;/span&gt;,
  mockServer_1  |       &lt;span class="s2"&gt;"queryStringParameters"&lt;/span&gt; : &lt;span class="o"&gt;{&lt;/span&gt;
  mockServer_1  |         &lt;span class="s2"&gt;"code"&lt;/span&gt; : &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"10969"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
  mockServer_1  |       &lt;span class="o"&gt;}&lt;/span&gt;
  mockServer_1  |     &lt;span class="o"&gt;}&lt;/span&gt;,
  mockServer_1  |     &lt;span class="s2"&gt;"times"&lt;/span&gt; : &lt;span class="o"&gt;{&lt;/span&gt;
  mockServer_1  |       &lt;span class="s2"&gt;"unlimited"&lt;/span&gt; : &lt;span class="nb"&gt;true
  &lt;/span&gt;mockServer_1  |     &lt;span class="o"&gt;}&lt;/span&gt;,
  mockServer_1  |     &lt;span class="s2"&gt;"timeToLive"&lt;/span&gt; : &lt;span class="o"&gt;{&lt;/span&gt;
  mockServer_1  |       &lt;span class="s2"&gt;"unlimited"&lt;/span&gt; : &lt;span class="nb"&gt;true
  &lt;/span&gt;mockServer_1  |     &lt;span class="o"&gt;}&lt;/span&gt;,
  mockServer_1  |     &lt;span class="s2"&gt;"httpResponse"&lt;/span&gt; : &lt;span class="o"&gt;{&lt;/span&gt;
  mockServer_1  |       &lt;span class="s2"&gt;"statusCode"&lt;/span&gt; : 200,
  mockServer_1  |       &lt;span class="s2"&gt;"body"&lt;/span&gt; : &lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;wheather&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: 20.5}"&lt;/span&gt;
  mockServer_1  |     &lt;span class="o"&gt;}&lt;/span&gt;
  mockServer_1  |   &lt;span class="o"&gt;}&lt;/span&gt;
  mockServer_1  |  
  mockServer_1  | 2020-04-11 15:52:30  org.mockserver.cli.Main  INFO  logger level is INFO, change using:
  mockServer_1  |  - &lt;span class="s1"&gt;'ConfigurationProperties.logLevel(String level)'&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;Java code,
  mockServer_1  |  - &lt;span class="s1"&gt;'-logLevel'&lt;/span&gt; &lt;span class="nb"&gt;command &lt;/span&gt;line argument,
  mockServer_1  |  - &lt;span class="s1"&gt;'mockserver.logLevel'&lt;/span&gt; JVM system property or,
  mockServer_1  |  - &lt;span class="s1"&gt;'mockserver.logLevel'&lt;/span&gt; property value &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s1"&gt;'mockserver.properties'&lt;/span&gt; 
  mockServer_1  | 2020-04-11 15:52:30  org.mockserver.log.MockServerEventLog  INFO  started on port: 1080 




&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Sending requests
&lt;/h2&gt;

&lt;p&gt;Open a new terminal window and enter:&lt;/p&gt;

&lt;p&gt;To see info about your available containers enter again:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can now see some info about your running container. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;curl localhost:1080/api/v1/weather&lt;span class="se"&gt;\?&lt;/span&gt;code&lt;span class="se"&gt;\=&lt;/span&gt;10969           


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You should see the response:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{"wheather": 20.5}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And thats it! &lt;/p&gt;

&lt;p&gt;You've got yourself a local server where you can mock simple and complex requests and responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Useful links:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.9.x" rel="noopener noreferrer"&gt;REST API Swagger docs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>testing</category>
    </item>
    <item>
      <title>Concise and type-safe scripting with kotlin</title>
      <dc:creator>Iury Souza</dc:creator>
      <pubDate>Sat, 07 Nov 2020 18:32:44 +0000</pubDate>
      <link>https://dev.to/iurysza/concise-and-type-safe-scripting-with-kotlin-17fo</link>
      <guid>https://dev.to/iurysza/concise-and-type-safe-scripting-with-kotlin-17fo</guid>
      <description>&lt;p&gt;A kotlin script is a way to &lt;strong&gt;compile&lt;/strong&gt; and &lt;strong&gt;run&lt;/strong&gt; &lt;code&gt;Kotlin&lt;/code&gt; code easily. &lt;br&gt;
Scripts are a powerful tool when you want to automate any kind of work. The most used languages for scripting tend to be &lt;code&gt;python&lt;/code&gt; &lt;br&gt;
or &lt;code&gt;bash&lt;/code&gt;/&lt;code&gt;shell&lt;/code&gt; but, what if you could get the same task done with &lt;code&gt;Kotlin&lt;/code&gt;?&lt;br&gt;
But not just that. What if you had access to any java or kotlin library in your scripts?&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;Kscript&lt;/code&gt; you can easily do that! Besides it also offers a lot of features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scripts caching: Running the same script will be way faster the second time.&lt;/li&gt;
&lt;li&gt;Maven dependencies&lt;/li&gt;
&lt;li&gt;IntelliJ support&lt;/li&gt;
&lt;li&gt;Bootstrap header&lt;/li&gt;
&lt;li&gt;Check the &lt;a href="https://github.com/holgerbrandl/kscript"&gt;kscript repo&lt;/a&gt; for the full feature set.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Trying it out
&lt;/h3&gt;

&lt;p&gt;Install it with &lt;a href="https://sdkman.io"&gt;sdk man&lt;/a&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="nv"&gt;$ &lt;/span&gt;sdk &lt;span class="nb"&gt;install &lt;/span&gt;kscript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Now let's create a &lt;code&gt;.kts&lt;/code&gt; file and try importing some libraries to create an embedded server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;!/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="n"&gt;kscript&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;MavenRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bintray-ktor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"https://dl.bintray.com/kotlin/ktor"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;DependsOnMaven&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"io.ktor:ktor-server-netty:1.2.6"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.ktor.application.*&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.ktor.http.*&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.ktor.response.*&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.ktor.routing.*&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.ktor.server.engine.*&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.ktor.server.netty.*&lt;/span&gt;

&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"starting server..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;server&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;embeddedServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Netty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;routing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respondText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Plain&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;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, lets run it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kscript kscript-server.kts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open your browser on &lt;code&gt;localhost:8080/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Cool, right?&lt;/p&gt;

&lt;p&gt;But if you’re like me you probably do most of your work on the IDE. So, let’s try that now.&lt;/p&gt;

&lt;p&gt;If you have Intelij Idea on your machine you can type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kscript &lt;span class="nt"&gt;--idea&lt;/span&gt; kscript-server.kts 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and it will generate a Gradle Kotlin project with all dependencies declared with the &lt;code&gt;@file&lt;/code&gt; convention and add them to a Gradle file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#Protip&lt;/strong&gt;: If syntax highlighting is not working properly, just right click on the &lt;code&gt;build.gradle&lt;/code&gt; file select &lt;code&gt;Import Gradle project&lt;/code&gt; &lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>scripting</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
