<?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: Chathula Sampath</title>
    <description>The latest articles on DEV Community by Chathula Sampath (@chathula).</description>
    <link>https://dev.to/chathula</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%2F18755%2F97339d29-639e-41bc-9409-f7033f58e779.jpeg</url>
      <title>DEV Community: Chathula Sampath</title>
      <link>https://dev.to/chathula</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chathula"/>
    <language>en</language>
    <item>
      <title>What is your preferable NPM package boilerplate?</title>
      <dc:creator>Chathula Sampath</dc:creator>
      <pubDate>Sun, 26 Apr 2020 07:14:10 +0000</pubDate>
      <link>https://dev.to/chathula/what-is-your-ppreferable-npm-package-boilerplate-4b8h</link>
      <guid>https://dev.to/chathula/what-is-your-ppreferable-npm-package-boilerplate-4b8h</guid>
      <description>&lt;p&gt;There are lot of people who contributes to open source community. This is mainly about javascript community. So just want to discuss and share what are your preferable NPM package boilerplates that you would use when you start creating a new NPM module.&lt;/p&gt;

&lt;p&gt;There will be multiple boilerplates for different projects. No matter what share it. As an example there will be typescript, react, vue, typescript + react etc package boilerplates. &lt;/p&gt;

&lt;p&gt;This is what i use for react and typescript.&lt;/p&gt;

&lt;p&gt;tsdx: &lt;a href="https://github.com/jaredpalmer/tsdx"&gt;https://github.com/jaredpalmer/tsdx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you!&lt;/p&gt;

&lt;p&gt;Reach Me:&lt;br&gt;
&lt;a href="https://chathula.dev"&gt;Blog&lt;/a&gt;&lt;br&gt;
&lt;a href="https://twitter.com/chathulaC"&gt;Twitter&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/chathula"&gt;Linkedin&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>node</category>
    </item>
    <item>
      <title>How to set up a CI/CD Pipeline for a node.js app with Github Actions</title>
      <dc:creator>Chathula Sampath</dc:creator>
      <pubDate>Mon, 16 Mar 2020 20:21:08 +0000</pubDate>
      <link>https://dev.to/chathula/how-to-set-up-a-ci-cd-pipeline-for-a-node-js-app-with-github-actions-32h0</link>
      <guid>https://dev.to/chathula/how-to-set-up-a-ci-cd-pipeline-for-a-node-js-app-with-github-actions-32h0</guid>
      <description>&lt;h2&gt;
  
  
  Github Actions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/features/actions"&gt;Github Actions&lt;/a&gt;&lt;/strong&gt; is a tool/service which can be used to test, build and deploy your code by creating a CI/CD pipeline. it helps to automate your workflow like other tools/services such as &lt;strong&gt;Jenkins, Gitlab CI,&lt;/strong&gt; etc. Github Actions uses &lt;strong&gt;YAML&lt;/strong&gt; as the language to write the jobs/steps which need to perform on certain events. This can be used for many things such as deploy a web service, build a container app, publish packages to registries, or automate welcoming new users to your open source projects. The biggest feature in Github Actions for me is Matrix Builds(In this tutorial also I am using that for demonstrating purpose). it means you can run your workflow that simultaneously tests across multiple operating systems and versions of your runtime. (As an example you can run your workflow on Windows, Mac, and Linux with NodeJS 8.x And 10.x)&lt;/p&gt;

&lt;h2&gt;
  
  
  What are we going to build?
&lt;/h2&gt;

&lt;p&gt;We are going to build a simple NodeJS app and host it(in this guide, I am going to use DigitalOcean instance. you can use whatever you want). This guide will show you how to config and work with Github Actions to deploy the NodeJS app to your server. Whenever you change something in code and push, Github will fire an event and will start to do the things we said. here we are going to install dependencies, run the test we wrote, if all tests are passed, Github action will deploy the app to the server. Another bonus thing that we are going to do here is run &lt;strong&gt;Matrix builds&lt;/strong&gt;. it means we run our tests on multiple NodeJS versions. (you can use Multiple Operating Systems as well). it will help us to confirm our app works on (multiple Operating Systems) and multiple NodeJS versions without an issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a NodeJS App
&lt;/h2&gt;

&lt;p&gt;As the first thing in this guide, we are going to create a NodeJS application locally. Here we just create a simple application that responds with the &lt;strong&gt;“Hello World”&lt;/strong&gt; text. First, we will create our Github Repository. The below screenshot will show how I did it. You can change the settings as you want such as setting &lt;strong&gt;private/public&lt;/strong&gt; accessibility of your repository.&lt;/p&gt;

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

&lt;p&gt;Now let’s clone the repository and navigate to it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone [git@github.com](mailto:git@github.com):&amp;lt;username&amp;gt;/node-github-demo.git
cd node-github-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then run below commands to create &lt;strong&gt;package.json&lt;/strong&gt; file and add the required dependencies and other content and then run following command to install the dependencies. Here are some descriptions of the packages that we use.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init // fill the required things CLI asked
npm i express
npm i mocha supertest --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;express&lt;/strong&gt;: Node framework&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;mocha&lt;/strong&gt;: Test framework for NodeJS ( You can choose another testing framework if you wish like Jasmin, Jest, Tape, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;supertest&lt;/strong&gt;: Provide a high-level abstraction for testing HTTP&lt;/p&gt;

&lt;p&gt;npm install&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Okay, now everything is ready. let’s create a file called &lt;strong&gt;index.js&lt;/strong&gt; to write the code to create an express server and show the &lt;strong&gt;“Hello World”&lt;/strong&gt; text as the response of the &lt;strong&gt;“/”&lt;/strong&gt; endpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// importing express framework&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Respond with "hello world" for requests that hit our root "/"&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// listen to port 7000 by default&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;7000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Server is running&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can run the above code using the below command. Then visit &lt;strong&gt;&lt;a href="http://localhost:7000"&gt;http://localhost:7000&lt;/a&gt;&lt;/strong&gt; to see the “Hello World” output.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Write Test Cases
&lt;/h2&gt;

&lt;p&gt;Now we are going to write the test case to test our &lt;strong&gt;“/”&lt;/strong&gt; endpoint response equals to &lt;strong&gt;“Hello World”&lt;/strong&gt;. to do that, let’s create a folder called &lt;strong&gt;/test/&lt;/strong&gt; and create a file called &lt;code&gt;test.js&lt;/code&gt; inside that. Now let’s write the test code as bellow.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;supertest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET /&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;respond with Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run tests add below content to your &lt;strong&gt;package.json&lt;/strong&gt; file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
    "test": "mocha ./test/* --exit"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;now just run below command to run test cases you wrote to see whether it gets passed or not.&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;Here is the output.&lt;/p&gt;

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

&lt;p&gt;Now we can push our changes to Github repository we created. Before that create &lt;strong&gt;.gitignore&lt;/strong&gt; file and add files/folders you need to ignore from the git repository. here is my example &lt;a href="https://github.com/Chathula/node-github-demo/blob/master/.gitignore"&gt;**.gitignore&lt;/a&gt;** file I used in this guide. Now let’s push the files to Github.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "node app with test cases"
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Create Our Server (DigitalOcean)
&lt;/h2&gt;

&lt;p&gt;Okay, now we have finished writing our NodeJS app and need to create a server to deploy it to serve to the world. in this case as I said earlier I am going to use &lt;strong&gt;DigitalOcean&lt;/strong&gt; droplet in this guide. Below screenshots will show you what needs to be filled when you create the Droplet in &lt;strong&gt;DigitalOcean&lt;/strong&gt; and how it looks like after you create that. In this guide, I am using the existing NodeJS image droplet via the &lt;strong&gt;DigitalOcean&lt;/strong&gt; M*&lt;em&gt;arketplace&lt;/em&gt;&lt;em&gt;. you can do the same thing by navigating to **Create(from top bar) -&amp;gt; Droplets -&amp;gt; Marketplace&lt;/em&gt;*&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n4eD-EhY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2512/1%2Ad5_l7_Tvi-3Rj-V5BdyadQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n4eD-EhY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2512/1%2Ad5_l7_Tvi-3Rj-V5BdyadQ.png" alt="" width="800" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: when you create droplet by selecting the Authentication option as &lt;strong&gt;SSH key&lt;/strong&gt;, you need to add your local machine SSH key to Droplet. to do the that first generate it and then copy it and paste*&lt;em&gt;(to paste click New SSH Key button)&lt;/em&gt;*. to generate and get a copy of your SSH key run the following commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: here, I am using Linux. if you are on different OS, this will be a bit different. this works well on Linux and Mac.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-keygen -t rsa
cat ~/.ssh/id_rsa.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Deploy NodeJS App on Server
&lt;/h2&gt;

&lt;p&gt;Now we need to deploy our application in our Digitalocean server. to do that, we are going to create a new user.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh root@SERVER.IP
adduser &amp;lt;lastname&amp;gt;
usermod -a -G sudo &amp;lt;username&amp;gt;
su — username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Run below commands to give that user login access via SSH without a password. then you can easily log in to the server by running ssh @SERVER.IP.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd
mkdir .ssh
chmod 700 .ssh/
vim ~/.ssh/authorized_keys # here paste your local ssh key as we did earlier
chmod 600 ~/.ssh/*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now install the git in the server. Then pull the source code and run it on the server.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install git
ssh-keygen
cat ~/.ssh/id_rsa.pub #copy the text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we copied our new user ssh key. just paste it as a Github repository deploy key. then clone the repository and run it on the server.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone [git@github.com](mailto:git@github.com):&amp;lt;username&amp;gt;/node-github-demo.git
cd node-github-demo
npm install --production
sudo ufw allow 7000 # this will open port 7000 to access via web
sudo npm install pm2 -g
pm2 start index.js --name node-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zu0MEI77--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Afahpg4xLYJuBugptZBknVQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zu0MEI77--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Afahpg4xLYJuBugptZBknVQ.png" alt="" width="716" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now our app is running through PM2 as node-app. just got to &lt;a href="http://SERVER.IP:3000"&gt;http://SERVER.IP:7000&lt;/a&gt; to check that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gYkeEeK1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ArhUbWpjTv9mFGUW-HfMEeA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gYkeEeK1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ArhUbWpjTv9mFGUW-HfMEeA.png" alt="The app is running!" width="493" height="216"&gt;&lt;/a&gt;&lt;em&gt;The app is running!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a CI/CD Pipeline on Github Actions
&lt;/h2&gt;

&lt;p&gt;First Add the following secretes to use with the Github Actions workflow script. to get the SSH_KEY, just run following command on your local machine which already has the access to Digitalocean server. Then copy the content and paste the value into the SSH_KEY secret.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat ~/.ssh/id_rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

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

&lt;p&gt;Now we can create our Github Actions CI/CD Pipeline. Just go to the repository and click Actions tab.&lt;/p&gt;

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

&lt;p&gt;Click the Node.js setup the workflow button. and it will open up a text editor. paste the following yml file content.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Node Github CI&lt;/span&gt;

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

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;8.x&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;10.x&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;12.x&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use Node.js ${{ matrix.node-version }}&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v1&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.node-version }}&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install and test&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;npm install&lt;/span&gt;
        &lt;span class="s"&gt;npm test&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;CI&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SSH and deploy node app&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appleboy/ssh-action@master&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SSH_HOST }}&lt;/span&gt;
        &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SSH_USERNAME }}&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SSH_KEY }}&lt;/span&gt;
        &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SSH_PORT }}&lt;/span&gt;
        &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;cd ~/node-github-demo&lt;/span&gt;
          &lt;span class="s"&gt;git pull origin master&lt;/span&gt;
          &lt;span class="s"&gt;npm install --production&lt;/span&gt;
          &lt;span class="s"&gt;pm2 restart node-app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I will explain the above YAMLcontent.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Line 1: name set the workflow name.&lt;br&gt;
Line 3–6: on will check which git event we need to run the jobs. here we have set when something gets pushed to master branch, run following jobs(in this case those are test and deploy).&lt;br&gt;
Line 8–28: here in the jobs we have created a job called test. by setting runs-on we can set the runner. in this case, we have set it to ubuntu-latest. we can use Windows, Mac as well if we want. by setting astrategy we can set a build matrix. it uses to run the this test job under different node versions at this moment. under setps we can set the different tasks we need to run on specific job(in this case test job).&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;By setting uses we can run different actions. above case, we check out a copy of the repository. in the next line, we have set a name for this task. in the next line, we have used the following setup-node action with v1 git tag. also, we have passed an input parameter for the actions called node-version. in this case for matrix builds we have to set that version dynamically.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v1&lt;/span&gt;
    &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.node-version }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Also in the next line, we have set the name for that task as well. after that by setting run we ran multiple commands on the Operating system shell. in this case, it is, Ubuntu. by setting env we have the the CI env variable to true(we can set any other environment variables when we want).&lt;br&gt;
Line 30–46: we have created another job called deploy. in that case, also we have used same syntax as above. only new thing that we used is, needs. it uses to say if only specific job or jobs passed, then only run this job. in our case deploy job only runs when the test job gets passed.&lt;br&gt;
in this case we have used another Github action called appleboy/&lt;a href="mailto:ssh-action@master"&gt;ssh-action@master&lt;/a&gt;. it needs few input parameters, we have set that. (in this case, those are SSH host, key, username, port and the script which needs to run on the server after connecting to it via SSH).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then click start commit and commit the changes. Now it will run the script. to see the changes. let’s do a change in the source code and push it into the master.&lt;/p&gt;

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

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

&lt;p&gt;Here you can see our test failed. as that it didn’t run the deployment. in the workflow yml we have set the&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as this, deployjob only runs when testjob gets passed. so we can now update the test and re-check it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qPJ4rH81--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AxyaMGgJ7HJ07VkFBouxvFQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qPJ4rH81--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AxyaMGgJ7HJ07VkFBouxvFQ.png" alt="" width="768" height="727"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, now it works! it ran the deploy job as well. we can see our changes by visiting toSERVER.IP:7000&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3dFlZsWu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ApdiRGXeqgE7eBTMEdIdAPw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3dFlZsWu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ApdiRGXeqgE7eBTMEdIdAPw.png" alt="" width="407" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; in this tutorial, I have used matrixbuild for &lt;strong&gt;Github Actions&lt;/strong&gt;. it means it will run the test(in this case) on &lt;strong&gt;different NodeJS versions&lt;/strong&gt;. &lt;strong&gt;we can expand this to run on different NodeJS versions in different Operating systems as well.&lt;/strong&gt; learn more about it &lt;a href="https://help.github.com/en/actions/configuring-and-managing-workflows/configuring-a-workflow#configuring-a-build-matrix"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References:&lt;/strong&gt; &lt;a href="https://medium.com/@mosheezderman/how-to-set-up-ci-cd-pipeline-for-a-node-js-app-with-jenkins-c51581cc783c"&gt;https://medium.com/@mosheezderman/how-to-set-up-ci-cd-pipeline-for-a-node-js-app-with-jenkins-c51581cc783c&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions"&gt;https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://help.github.com/en/actions/language-and-framework-guides/using-nodejs-with-github-actions"&gt;https://help.github.com/en/actions/language-and-framework-guides/using-nodejs-with-github-actions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Special thanks go to &lt;strong&gt;&lt;a href="https://twitter.com/appleboy"&gt;appleboy&lt;/a&gt;&lt;/strong&gt; who created the ssh-deploy Github action.&lt;/p&gt;

&lt;p&gt;If you have any questions, please let me know.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;a href="https://github.com/Chathula/node-github-demo"&gt;Source Code&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Follow Me on &lt;a href="https://twitter.com/ChathulaC"&gt;Twitter&lt;/a&gt;&lt;br&gt;
Connect me with &lt;a href="https://www.linkedin.com/in/chathula/"&gt;LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Originally posted on &lt;a href="https://medium.com/@chathula/how-to-set-up-a-ci-cd-pipeline-for-a-node-js-app-with-github-actions-2073201b0df6"&gt;Medium&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>github</category>
      <category>devops</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Manage project from start to end</title>
      <dc:creator>Chathula Sampath</dc:creator>
      <pubDate>Fri, 20 Dec 2019 20:04:01 +0000</pubDate>
      <link>https://dev.to/chathula/manage-project-from-start-to-end-52o5</link>
      <guid>https://dev.to/chathula/manage-project-from-start-to-end-52o5</guid>
      <description>&lt;p&gt;Hey all,&lt;/p&gt;

&lt;p&gt;Just wanted to know your ideas and approches which used to manage a software project from start to end. how do you start your work, how do you release something for production first. how long normally you take to do that.how to define basic features that you need to have in the project? What kind of architectural approch you take when you start something first? How to decide the tech stack?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>idea</category>
      <category>productivity</category>
      <category>projectmanagement</category>
    </item>
    <item>
      <title>Dev.to Followers Notification</title>
      <dc:creator>Chathula Sampath</dc:creator>
      <pubDate>Wed, 06 Nov 2019 09:16:51 +0000</pubDate>
      <link>https://dev.to/chathula/dev-to-followers-notification-3k84</link>
      <guid>https://dev.to/chathula/dev-to-followers-notification-3k84</guid>
      <description>&lt;p&gt;Everytime when i visit to dev.to, after few minutes i get an email by saying that someone has followed me. Is this some kind of way that dev.to has implemented to get visitors back to the site or when user visit to the site only dev.to sends the notifications to users about their followers?&lt;/p&gt;

&lt;p&gt;Does anybody notice this also?&lt;/p&gt;

</description>
      <category>devto</category>
      <category>followers</category>
      <category>discuss</category>
    </item>
    <item>
      <title>What is the tech stack of pusher.com?</title>
      <dc:creator>Chathula Sampath</dc:creator>
      <pubDate>Sun, 27 May 2018 17:00:38 +0000</pubDate>
      <link>https://dev.to/chathula/what-is-the-tech-stack-of-pushercom-178o</link>
      <guid>https://dev.to/chathula/what-is-the-tech-stack-of-pushercom-178o</guid>
      <description>&lt;p&gt;Does anyone has an idea about &lt;a href="https://pusher.com/"&gt;pusher&lt;/a&gt; tech stack? because it is hard to scale websocket stuff. how pusher does it? i like to know the way that they handle their traffic with their tech stack and infrastructure. &lt;/p&gt;

&lt;p&gt;Thank You&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>scale</category>
      <category>tech</category>
      <category>stack</category>
    </item>
  </channel>
</rss>
