<?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: Lampros Papadimitriou</title>
    <description>The latest articles on DEV Community by Lampros Papadimitriou (@trelobifteki).</description>
    <link>https://dev.to/trelobifteki</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%2F498834%2F661d52e3-7b66-42a8-834a-73d258576272.jpeg</url>
      <title>DEV Community: Lampros Papadimitriou</title>
      <link>https://dev.to/trelobifteki</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/trelobifteki"/>
    <language>en</language>
    <item>
      <title>Complete Jenkinsfile for Vue.js apps</title>
      <dc:creator>Lampros Papadimitriou</dc:creator>
      <pubDate>Thu, 04 Feb 2021 21:38:12 +0000</pubDate>
      <link>https://dev.to/trelobifteki/complete-jenkinsfile-for-vue-js-apps-57bc</link>
      <guid>https://dev.to/trelobifteki/complete-jenkinsfile-for-vue-js-apps-57bc</guid>
      <description>&lt;h2&gt;
  
  
  About
&lt;/h2&gt;

&lt;p&gt;After working on developing the build pipelines for my company, I noticed how modern building tools can help with the automation of important tasks in frontend development.&lt;/p&gt;

&lt;p&gt;I also migrated my personal website to use Jenkins for automatically building and deploying it. This guide explains how I was able to do it.&lt;/p&gt;

&lt;p&gt;The technology stack I am using for my website is the following&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Vue.js&lt;/li&gt;
&lt;li&gt;  Typescript&lt;/li&gt;
&lt;li&gt;  NPM&lt;/li&gt;
&lt;li&gt;  Eslint&lt;/li&gt;
&lt;li&gt;  Jest&lt;/li&gt;
&lt;li&gt;  Cypress&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Jenkinsfile
&lt;/h2&gt;

&lt;p&gt;I personally prefer to give freedom to developers and let them modify the building process as they need. Each git project also contains the Jenkinsfile in the root folder. We setup a Jenkins project as following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Add a Pipeline option to job&lt;/li&gt;
&lt;li&gt;  Set "Pipeline Script from SCM"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have worked in the past for projects where the building process and Jenkins were part of the admin team. As frontend developers we had difficulties to introduce new processes and steps in the pipeline and it constrained us to use new technologies we wanted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install dependencies
&lt;/h2&gt;

&lt;p&gt;It is a common &lt;em&gt;but wrong&lt;/em&gt; practice to install dependencies in CI pipelines using the following command:&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;This is actually wrong, since npm install &lt;em&gt;may&lt;/em&gt; install a newer minor release for either your dependencies and/or sub-dependencies.&lt;/p&gt;

&lt;p&gt;In a nutshell: This way it is possible that your build works on your developer laptop but it fails to compile in Jenkins, simply because &lt;code&gt;npm install&lt;/code&gt; installed a minor sub-dependency that had a breaking change.&lt;/p&gt;

&lt;p&gt;In order to avoid this issue simple use:&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;and add &lt;code&gt;package-lock.json&lt;/code&gt; in GIT. Believe me, this is a life savior! It will &lt;em&gt;always&lt;/em&gt; install the exact package and versions listed in this file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Audit dependencies
&lt;/h2&gt;

&lt;p&gt;There is no need for anything else than:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm audit --parseable --production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This way we are sure that main dependencies have no security issues. I am not checking for any vulnerabilities in dev packages since they are not directly used and it is not possible at the moment to define a &lt;em&gt;threshold&lt;/em&gt; to exclude minor issues.&lt;/p&gt;

&lt;p&gt;I am also checking if packages are outdated by executing the command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm outdated || exit 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This way the pipeline won't fail if the packages are outdated. It is also not possible here to define a threshold here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check linting
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Eslint&lt;/em&gt; is my favorite option for linting and format checks, since the&lt;br&gt;
integration with IDEs and console command is &lt;em&gt;almost perfect&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;If you are using &lt;em&gt;vue-cli&lt;/em&gt; to setup your project, we simply need to execute in Jenkinsfile:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run lint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Unit testing
&lt;/h2&gt;

&lt;p&gt;A unit testing &lt;em&gt;with coverage&lt;/em&gt; is another safety lock for capturing bugs before entering&lt;br&gt;
production.&lt;/p&gt;

&lt;p&gt;The following software has been used for this step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  jest&lt;/li&gt;
&lt;li&gt;  @vue/cli-plugin-unit-jest&lt;/li&gt;
&lt;li&gt;  jest-junit&lt;/li&gt;
&lt;li&gt;  Coberture jenkins plugin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simple execute the following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run test:unit -- --ci --coverage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;After successfully integrating Jenkins with Jest you will get a nice overview of the test&lt;br&gt;
results directly into Jenkins:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TiMSjhIY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gpc91qroet7m9r53yjn9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TiMSjhIY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gpc91qroet7m9r53yjn9.jpg" alt="Screenshot 1"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  E2E testing
&lt;/h2&gt;

&lt;p&gt;I used an end-to-end testing as a smoke test for my website. This way I am sure that the website was deployed successfully.&lt;/p&gt;

&lt;p&gt;I chose for this case &lt;em&gt;nightwatch&lt;/em&gt; and installed it using vue-cli:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vue add e2e-nightwatch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;After building the application, I made the &lt;em&gt;dist&lt;/em&gt; directory as the root directory for my web server.&lt;br&gt;
Once it is successfully build, I can execute the smoke test as following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run test:e2e -- --headless --url https://www.trelobifteki.com --config video=false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Some points there:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  I used &lt;code&gt;--headless&lt;/code&gt; since this is an automated test (no interaction is required)&lt;/li&gt;
&lt;li&gt;  I am using the actual URL of my website for end-to-end testing&lt;/li&gt;
&lt;li&gt;  I deactivated video recording (since I don't need it)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Complete example
&lt;/h2&gt;

&lt;p&gt;This is the actual pipeline I am using in my &lt;a href="https://github.com/trelo-bifteki/www.trelobifteki.com/"&gt;project&lt;/a&gt;. Feel free to check it out and experiment with it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;
  &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Check for vulnerabilities'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'npm audit --parseable --production'&lt;/span&gt;
        &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'npm outdated || exit 0'&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'download dependencies'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'npm ci'&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Check linting'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'npm run lint'&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Check unit:test'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'npm run test:unit -- --ci --coverage'&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;always&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;junit&lt;/span&gt; &lt;span class="s1"&gt;'junit.xml'&lt;/span&gt;
          &lt;span class="n"&gt;cobertura&lt;/span&gt; &lt;span class="nl"&gt;coberturaReportFile:&lt;/span&gt; &lt;span class="s1"&gt;'coverage/cobertura-coverage.xml'&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Build'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'npm run build'&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Check unit:e2e'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'npm run test:e2e -- --headless --url https://www.trelobifteki.com --config video=false'&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>jenkins</category>
      <category>vue</category>
      <category>npm</category>
    </item>
  </channel>
</rss>
