<?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>Forem: Pooria A</title>
    <description>The latest articles on Forem by Pooria A (@opshack).</description>
    <link>https://forem.com/opshack</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%2F174988%2Fc85cb388-97b4-473d-97d6-f7953086a705.jpg</url>
      <title>Forem: Pooria A</title>
      <link>https://forem.com/opshack</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/opshack"/>
    <language>en</language>
    <item>
      <title>Automatic deployment from Github to your server with no third party app</title>
      <dc:creator>Pooria A</dc:creator>
      <pubDate>Sun, 24 Nov 2019 09:34:41 +0000</pubDate>
      <link>https://forem.com/opshack/automatic-deployment-from-github-to-your-server-with-no-third-party-app-3f5j</link>
      <guid>https://forem.com/opshack/automatic-deployment-from-github-to-your-server-with-no-third-party-app-3f5j</guid>
      <description>&lt;p&gt;When it comes to setting up a deployment pipeline I believe the number of solutions in the wild are countless. If we are on AWS we can use Code Deploy, Heroku, Zeit Now and Netlify provide their own solutions and of course one of the popular ones is to delegate the task to your CI/CD server (Travis, Circle CI etc) to handle it. If you are using Docker containers the best orchestrator tools to use are AWS ECS, Swarm and Kubernetes. Most probably if you are working with a bigger team you have Dev-Ops team mates to handle it and you might take your infrastructure as granted! 😐 However, if like me you joined a startup and the deployment process was manual (SSH to server, git pull, etc) and you wrote some bash scripts to do it for them you might want to embrace your inner nerd 🤓 and level up your deployment game. In this case, running your bash scripts automatically upon merging a Pull Request on Github would make everyone happy and that's not rocket science so let's do it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;To automatically deploy your code after merging pull requests to branches dev and master.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things we use
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Node JS&lt;/li&gt;
&lt;li&gt;Bash Scripts&lt;/li&gt;
&lt;li&gt;Github Webhooks&lt;/li&gt;
&lt;li&gt;SSH command line&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Let's say we have two versions of our website that we need to automatically deploy. One is called &lt;code&gt;stage&lt;/code&gt; and represents the latest merged commits. These changes are often buggy and not reliable so we want only the internal team have access to it. "stage" represents our &lt;code&gt;dev&lt;/code&gt; branch in Github. The second version of the website is called "prod" and will rerpresent the &lt;code&gt;master&lt;/code&gt; branch in Github. This branch is (hopefully) stable and has passed the QA team and is considered safe for end-users. This version is the one that everyone outside the company know as our website URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Clone your Git repositories
&lt;/h3&gt;

&lt;p&gt;If you already don't have your github repositories cloned in the server you have to do it.&lt;/p&gt;

&lt;p&gt;Make two directories called : &lt;code&gt;prod&lt;/code&gt; and &lt;code&gt;stage&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;live stage
git clone git@github.com:p0o/your_repo.git
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; your_repo/. ./prod/your_repo
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; your_repo/. ./stage/your_repo
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ./your_repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to add the extra &lt;code&gt;.&lt;/code&gt; after your_repo, this a special &lt;code&gt;cp&lt;/code&gt; syntax that allows copying hidden files and folders inside your folder as well (we need it to copy .git folder as well).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wild Assumption:&lt;/strong&gt; I assume you are familiar with the basics of managing a server and your can run your websites in the URL you want with a proper SSL certificate. I use Nginx for this purpose but I'm not gonna explain these steps in the post. You might search if you are not sure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Make bash scripts
&lt;/h3&gt;

&lt;p&gt;We need to have two bash scripts to handle the deployment for each of these cases. If you need to build your files and  Let's create a directory in our server's home directory and start from there. I call this directory &lt;code&gt;scripts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/
&lt;span class="nb"&gt;mkdir &lt;/span&gt;scripts
&lt;span class="nb"&gt;cd &lt;/span&gt;scripts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay let's proceed with making the bash files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; ./deploy_stage
&lt;span class="nb"&gt;touch&lt;/span&gt; ./deploy_prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give them execution permission:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ./deploy_stage
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ./deploy_prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Thanks to &lt;a href="https://dev.to/darksmile92"&gt;darksmile92&lt;/a&gt; for pointing this out)&lt;/p&gt;

&lt;p&gt;I will put the sample code for one of them, the other one is just a different folder and might have different environment variables according to your project dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Deploying stage your_repo"&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; ~/stage/your_repo &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git checkout dev &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git pull &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm i &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run build &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;pm2 stop your_repo_stage &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Installing:  done.'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;pm2 delete your_repo_stage &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;NODE_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;development pm2 &lt;span class="nt"&gt;--name&lt;/span&gt; your_repo_stage start npm &lt;span class="nt"&gt;--&lt;/span&gt; start &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"your_repo deployed successfully"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This bash script will basically fetch the latest code from github, install dependencies, build the script (if required) and run it using &lt;a href="https://www.npmjs.com/package/pm2" rel="noopener noreferrer"&gt;PM2&lt;/a&gt;. If you are not familiar, PM2 is a very useful process management tool and you can easily install it using NPM.&lt;/p&gt;

&lt;p&gt;Also it's good to mention that I chained my whole process with logical AND (&amp;amp;&amp;amp;) because I wan to exit the execution in case one of the processes failed. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Write code to handle the webhook events
&lt;/h2&gt;

&lt;p&gt;In order to get notified anytime something happens in Github we have to subscribe to their Webhook API which essentially means giving some URLs to github so they would send some information to it. These URLs have to be public and they can run scripts that would lead to deployment of your code so having them accessible to anyone except Github servers would have serious security implications (e.g Denial Of Service attack).&lt;/p&gt;

&lt;p&gt;Github is using a SH1 HMAC signature to verify the JSON object it's sending you. We will have this signature hash in the &lt;code&gt;X-Hub-Signature&lt;/code&gt; value of header. Since taking care of all this is a bit complicated, we can use &lt;a href="https://www.npmjs.com/package/github-webhook-handler" rel="noopener noreferrer"&gt;github-webhook-handler package&lt;/a&gt; which is created exactly for the same purpose.&lt;/p&gt;

&lt;p&gt;We also need to run our bash script files from node. We can do it using native functions but I prefer to use &lt;a href="https://www.npmjs.com/package/shelljs" rel="noopener noreferrer"&gt;shellJs&lt;/a&gt; for the sake of simplicity.&lt;/p&gt;

&lt;p&gt;Okay enough ranting, here is the code you need:&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;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&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;createHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;github-webhook-handler&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;shell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shelljs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// We avoid to hardcode the secret in the code, you should provide it with an ENV variable before running this script&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MY_SECRET&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&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="c1"&gt;// You might use the same script for multiple repositories, this is only one of them&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;REPO_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my_repo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// port is default on 6767&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&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;6767&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createHandler&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MY_SECRET&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&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="nf"&gt;handler&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="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no such location&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="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&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="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pull_request&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;repository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Received a Pull Request for %s to %s&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// the action of closed on pull_request event means either it is merged or declined&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;repository&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;REPO_NAME&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;closed&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;// we should deploy now&lt;/span&gt;
    &lt;span class="nx"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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;shell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;~/scripts/deploy_stage&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="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Save it in a folder somewhere in your server and install the dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init
npm i github-webhook-handler shelljs &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then just run it with environment variable forever using PM2:&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;MY_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;MyGithubWebhookSecret pm2 &lt;span class="nt"&gt;--name&lt;/span&gt; github-deployer start node &lt;span class="nt"&gt;--&lt;/span&gt; ./index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Configure github webhook
&lt;/h2&gt;

&lt;p&gt;Now we just need to go to Github and introduce our webhook to github. But pay attention that in the previous step we ran the webhook on the port 6767 with no HTTPS. So you need to setup nginx and give it a proper domain with HTTPS. You can just put it on a path in your main domain but explaining that process is not in the scope of this article. Furtunately there are multiple articles in the web for you to look for.&lt;/p&gt;

&lt;p&gt;Go to the Setting tab of your repository and click on the Webhooks. In the right side of the page, click on the "Add Webhook" button.&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/.%2F1.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/.%2F1.png" alt="Add Webhook Page in Github"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the URL you introduced in your Nginx for the Node JS app we ran. Let's say it is &lt;a href="https://yourdomain.com/webhook" rel="noopener noreferrer"&gt;https://yourdomain.com/webhook&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose &lt;code&gt;application/json&lt;/code&gt; for the content-type and enter the secret we used to run our service with. In my example it was "MyGithubWebhookSecret" up there.&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/.%2F2.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/.%2F2.png" alt="Add Webhook Page in Github"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the section "Which events would you like to trigger this webhook?" click on "Let me select individual events" and find Pull Requests and check it:&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/.%2F3.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/.%2F3.png" alt="Pull Request event in Github Webhook config"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure everything else is unchecked and click "Add Webhook" to save it. We are all set now 🦸&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Test and verify
&lt;/h2&gt;

&lt;p&gt;Use PM2 to monitor the logs for the node js app we made just now. Enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pm2 log github_deployer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can see if any changes happens! Go to your repository and change something in a new branch. Submit a pull request and merge it. You should see your bash script in the log would perform a deployment and after that your changes should be reflected to the website. If you had any error, you can see it here in the log and well... do something about it 😂&lt;/p&gt;

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

&lt;p&gt;Even though I think the proposed solution in this article is fairly straightforward, it is not the best solution out there for this particular problem. Even my &lt;a href="https://fsociety.at" rel="noopener noreferrer"&gt;personal blog&lt;/a&gt; is using Zeit Now Github Integration to get deployed! However other solutions rely on third party apps and sometimes not accessible to certain teams according to their resources. In my case, the deployment scripts were already there, repositories were not using docker and I had very limited time to spend on this problem. Advance with it if you also happen to be in the same boat!&lt;/p&gt;

&lt;p&gt;This article is originally published on my blog with the title &lt;a href="https://fsociety.at/automatic-deployment-from-github-to-your-server-with-no-third-party-app/" rel="noopener noreferrer"&gt;Automatic deployment From Github to your server&lt;/a&gt; feel free to check it out for more posts! 👀&lt;br&gt;
You can also find me on twitter =&amp;gt; &lt;a href="https://twitter.com/p0oker" rel="noopener noreferrer"&gt;@p0oker&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>node</category>
      <category>javascript</category>
      <category>github</category>
    </item>
    <item>
      <title>Why is my browser sending an OPTIONS HTTP request instead of POST?</title>
      <dc:creator>Pooria A</dc:creator>
      <pubDate>Sat, 09 Nov 2019 20:49:08 +0000</pubDate>
      <link>https://forem.com/opshack/why-is-my-browser-sending-an-options-http-request-instead-of-post-5621</link>
      <guid>https://forem.com/opshack/why-is-my-browser-sending-an-options-http-request-instead-of-post-5621</guid>
      <description>&lt;p&gt;This issue caught my attention a few days ago that my colleagues were facing difficulty in using a new API developed in-house using Flask. The problem was that no matter what, the front-end developer couldn't make a call with correct &lt;code&gt;content-type&lt;/code&gt;. Even though that Axios uses JSON as the default content type, the call was always going with a &lt;code&gt;text/html&lt;/code&gt; format and everyone were getting frustrated 🤨.&lt;/p&gt;

&lt;p&gt;In the other hand, the back-end developer was showing her the result from &lt;a href="https://www.getpostman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt; (an application for developers to send HTTP calls) and everything was working fine there!&lt;/p&gt;

&lt;p&gt;I first tried to test if the end point is working fine or not. Me being a CLI guy, used my favorite HTTP client &lt;a href="https://httpie.org" rel="noopener noreferrer"&gt;HTTPie&lt;/a&gt; to do the basic call. It's something like CURL but looks better for the eyes!&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%2Ffsociety.at%2Fstatic%2Fc03069c1af479f1dd2dab7e05383f8b4%2F0c224%2F1.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%2Ffsociety.at%2Fstatic%2Fc03069c1af479f1dd2dab7e05383f8b4%2F0c224%2F1.png" alt="successful HTTP call" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nothing is wrong here if we test the API standalone with a HTTP client, but the axios request below would result in nothing.&lt;/p&gt;

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

&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://ENDPOITN_URL&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="na"&gt;field1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;something&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;field2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;something&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;My colleague moved forward and tried to enforce a &lt;code&gt;application/json&lt;/code&gt; content-type to axios. It's a bit weird but maybe somewhere else in the code the default for the axios is changed?&lt;/p&gt;

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

const customHeaders = {
  'content-type': 'application/json',
};

axios.post('https://ENDPOITN_URL', {
  field1: 'something',
  field2: 'something'
}, customHeaders);


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

&lt;/div&gt;

&lt;p&gt;Still no practical results. I asked for a screenshot and this is how it was looking like in the browser:&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%2Ffsociety.at%2Fstatic%2F3ef7f1ecb72da66b7d7f3466f9c525f1%2Faa6a0%2F2.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%2Ffsociety.at%2Fstatic%2F3ef7f1ecb72da66b7d7f3466f9c525f1%2Faa6a0%2F2.png" alt="browser screenshot, it's an OPTIONS call not a POST" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay let's take a closer look, there are two things to consider here:&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%2Ffsociety.at%2Fstatic%2F8e7ac9558d628bc469a8052662301154%2Fc0626%2F3.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%2Ffsociety.at%2Fstatic%2F8e7ac9558d628bc469a8052662301154%2Fc0626%2F3.png" alt="browser screenshot, OPTIONS call and content-type is text/html" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the POST method is never sent and only a method called OPTIONS is sent to the endpoint. The response headers from this call has a &lt;code&gt;content-type&lt;/code&gt; of 'text/html' which is the reason for all this evil here. So... what's going on?&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a preflight request?
&lt;/h2&gt;

&lt;p&gt;A preflight request, is a mechanism in CORS by the browser to check if the resource destination is willing to accept the real request or not. Afterall, why would a request be sent when the target host is not willing to receive it anyway?&lt;/p&gt;

&lt;p&gt;This mechanism works by sending an &lt;code&gt;OPTIONS&lt;/code&gt; HTTP method with &lt;code&gt;Access-Control-Request-Method&lt;/code&gt; and &lt;code&gt;Access-Control-Request-Headers&lt;/code&gt; in the header to notify the server about the type of request it wants to send. The response it retrieves determine if the actual request is allowed to be sent or not. This is a sample of a preflight request:&lt;/p&gt;

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

OPTIONS /resources/post-here/ HTTP/1.1 
Host: bar.other 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Language: en-us,en;q=0.5 
Accept-Encoding: gzip,deflate 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 
Connection: keep-alive 
Origin: http://foo.example 
Access-Control-Request-Method: POST 
Access-Control-Request-Headers: X-PINGOTHER, Content-Type


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

&lt;/div&gt;

&lt;p&gt;I highlighted the last three lines, because they are important fields in this call. Most developers are familiar with the Origin method because if it's not allowed from the backend API, you are not able to make AJAX calls to fetch the data. The other two parameters are overlooked 🧐 because most frameworks and libraries would take care of them anyway. For example any backend developer using express can simply add a middleware called CORS and make sure all the calls in his express app are providing those parameters for the OPTIONS method to the browsers.&lt;/p&gt;

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

var cors = require('cors')

app.use(cors()) // cool now everything is handled!


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

&lt;/div&gt;

&lt;p&gt;Whenever the server received that request, it should responds with &lt;code&gt;Access-Control-Allow-Methods&lt;/code&gt; and some other meta data to identify if the original request is acceptable or not! A sample response would look something like this (but it varies):&lt;/p&gt;

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

HTTP/1.1 204 No Content
Date: Mon, 01 Dec 2008 01:15:39 GMT 
Server: Apache/2.0.61 (Unix) 
Access-Control-Allow-Origin: http://foo.example 
Access-Control-Allow-Methods: POST, GET, OPTIONS 
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type 
Access-Control-Max-Age: 86400 
Vary: Accept-Encoding, Origin
Keep-Alive: timeout=2, max=100 
Connection: Keep-Alive


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

&lt;/div&gt;

&lt;p&gt;It's important to mention that, not all requests would preflight. As far as I know, only requests that are meant to be sent to a different origin and are not a form content-type are preflighted (excluding GET and HEADER methods).&lt;/p&gt;

&lt;h2&gt;
  
  
  So what was the problem?
&lt;/h2&gt;

&lt;p&gt;I tried to send a normal OPTIONS request to the endpoint to check the rules. I used the &lt;code&gt;--headers&lt;/code&gt; in HTTPie to only receive the header of the request.&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%2Ffsociety.at%2Fstatic%2F754b5a32e144fac76855b8aed8949dd8%2F639eb%2F4.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%2Ffsociety.at%2Fstatic%2F754b5a32e144fac76855b8aed8949dd8%2F639eb%2F4.png" alt="OPTIONS method returns a text/html content type" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Turned out that the value of the &lt;code&gt;content-type&lt;/code&gt; here is &lt;code&gt;text/html&lt;/code&gt; and that's why browser wouldn't push through with the actual POST method, however with a normal client it's acceptable. &lt;/p&gt;

&lt;p&gt;But we originally mentioned that most of the frameworks would handle this out of the box, so why here Flask is giving us wrong content-type? It's sort of a tricky situation... I figured if I send a normal POST request to the API without the required &lt;code&gt;body&lt;/code&gt; parameters, the endpoint will throw an error which is not properly handled!&lt;br&gt;
Well it's an obvious bug on the backend but probably they didn't care because it was an internal API and it was working fine with correct parameters. However, the OPTIONS method contains no &lt;code&gt;body&lt;/code&gt; parameters within and since the original API without params is returning a &lt;code&gt;text/html&lt;/code&gt; content (the web server error page) the OPTIONS method was also returning the same, mistakenly thinking that this API does not accept a JSON request 🤦&lt;/p&gt;

&lt;p&gt;I really enjoyed learning about this mechanism better through this article. If you like to learn more about this HTTP method and the process of preflight feel free to scavenge these links further:&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS" rel="noopener noreferrer"&gt;OPTIONS - MDN web docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/expressjs/cors" rel="noopener noreferrer"&gt;Express CORS middleware source code in github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods" rel="noopener noreferrer"&gt;Access-Control-Allow-Methods HTTP header&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;I originally published this article in &lt;a href="https://fsociety.at/why-my-browser-is-sending-an-OPTIONS-request-instead-of-POST/" rel="noopener noreferrer"&gt;my blog!&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>http</category>
      <category>browser</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Using GraphQL queries to separate pages and blog posts in Gatsby</title>
      <dc:creator>Pooria A</dc:creator>
      <pubDate>Wed, 05 Jun 2019 16:58:39 +0000</pubDate>
      <link>https://forem.com/opshack/using-graphql-queries-to-separate-pages-and-blog-posts-in-gatsby-1ke2</link>
      <guid>https://forem.com/opshack/using-graphql-queries-to-separate-pages-and-blog-posts-in-gatsby-1ke2</guid>
      <description>&lt;p&gt;When I started &lt;a href="https://fsociety.at"&gt;my blog&lt;/a&gt; with Gatsby one of my main problems was to filter out my "about me" or any other pages from the list of blog posts. If you don't use Markdown files for your static pages, this task is as simple as creating separate React components for each page. However, if like me, you wanted to use Markdown for your static pages you would have the problem of seeing your pages in the list of blog posts!&lt;/p&gt;

&lt;p&gt;In the beginning, I used my JavaScript skill to filter out the results but I wasn't happy with that. Recently I learned a better approach using GraphQL and that's what I'm describing in this post.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using frontmatter
&lt;/h1&gt;

&lt;p&gt;First, we need a mechanism to tag markdown files that we are using for our pages. Frontmatter (the fields specified on top of your markdown files) is a good place to tag some posts as pages. This is how I do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;My&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;page&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;title"&lt;/span&gt;
&lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;05/06/2019&lt;/span&gt;
&lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, in this markdown file I tagged the page property (could be anything else) as &lt;code&gt;true&lt;/code&gt;. Now in my index.js which I am listing all my blog posts, I have the possibility to filter out the markdown files that their &lt;code&gt;page&lt;/code&gt; property is false.&lt;/p&gt;

&lt;h1&gt;
  
  
  Excluding pages from blog posts
&lt;/h1&gt;

&lt;p&gt;At this moment that I have my page field ready in the frontmatter, removing the pages from blog posts results is as simple as one extra line to your GraphQL query:&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;// index.js (or wherever you are showing the list of your blog posts)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
  query {
    site {
      siteMetadata {
        title
      }
    }
    allMarkdownRemark(
      sort: { fields: [frontmatter___date], order: DESC }
      filter: { frontmatter: { page: {ne: true}}}
    ) {
      edges {
        node {
          excerpt
          fields {
            slug
          }
          frontmatter {
            date(formatString: "MMMM DD, YYYY")
            title
          }
        }
      }
    }
  }
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pay attention that I'm using the &lt;code&gt;filter&lt;/code&gt; argument on allMarkdownRemark query. &lt;code&gt;ne&lt;/code&gt; is a reserved keyword that would stand for "Not Equal". If you are not sure about the options available for filtering, you can always use the graqhiQL (accessible at &lt;strong&gt;localhost:8000/__graphql&lt;/strong&gt;) to check them out.&lt;/p&gt;

&lt;h1&gt;
  
  
  Querying the correct page
&lt;/h1&gt;

&lt;p&gt;Now we need to make a new component in our /pages directory and query the page correctly. However, for every page, we probably want to make a new component and there is no way to figure out which page, belongs to which component from the frontmatter.&lt;/p&gt;

&lt;p&gt;In order to simply serve a specific page in a component according to the name of the markdown file, we can simply use the slug field which is available in our GraphQL data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
query {
  site {
    siteMetadata {
      title
      author
    }
  }
  markdownRemark(
    fields: { slug: { eq: "/about-me/" }}
  ) {
    excerpt
    html
    frontmatter {
      title
      date
    }
  }
}
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this query, you can access to all the data of your post in &lt;code&gt;this.props.data.markdownRemark&lt;/code&gt; on the very same component you are executing this query with!&lt;/p&gt;

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

&lt;p&gt;This solution is appropriate for the use case of having limited pages with different designs. If you need to have a dynamic number of pages, you don't want to create new components for each of them and you need to make some changes in your &lt;code&gt;createPage&lt;/code&gt; function of you &lt;code&gt;gatsby-node.js&lt;/code&gt; file to render Page components differently.&lt;/p&gt;

</description>
      <category>gatsby</category>
      <category>react</category>
      <category>graphql</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Deploying a static Gatsby app using Now.sh</title>
      <dc:creator>Pooria A</dc:creator>
      <pubDate>Mon, 03 Jun 2019 05:26:04 +0000</pubDate>
      <link>https://forem.com/opshack/deploying-a-static-gatsby-app-using-now-sh-32ob</link>
      <guid>https://forem.com/opshack/deploying-a-static-gatsby-app-using-now-sh-32ob</guid>
      <description>&lt;p&gt;If you are making your new static website with Gatsby, you are probably looking for an easy way to build and deploy it. There are two generic ways for you to do so, using Github integration with Now.sh platform or manually using CLI. In this article, I explain both of these methods and reflect my experience of using Now.sh for the deployment of the very same blog you are reading.&lt;/p&gt;

&lt;p&gt;My assumption for this article is that you are familiar with Gatsby and recently started using Now.sh. Hopefully, you registered a domain with this service as well to create an alias for your deployment but it's not necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using CLI
&lt;/h2&gt;

&lt;p&gt;Now.sh has a very handy and powerful command line tool. No matter how much you like the idea of integration with Github or using the Desktop App, you would always need to go back to cli for advanced functions. I also hate to say it but it's much more reliable than Github integration since sometimes those services just stop working for technical reasons.&lt;/p&gt;

&lt;p&gt;In order to deploy you need to first download the command line tool from npm:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now you need to use this command in the terminal to log in to your now.sh account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;now login youremail@gmail.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter the password and you're all set. If you enter &lt;code&gt;now&lt;/code&gt; in every folder, it will upload all the files in that folder into a new address which is assignable to your domain. However, if you do it with a Gatsby blog you end up uploading all the files in your source directory including &lt;code&gt;package.json&lt;/code&gt; but not the static files. If you want to run a build in the cloud, you need to specify a configuration file for now.sh to understand how to build your files.&lt;/p&gt;

&lt;p&gt;Add a file with the name &lt;code&gt;now.json&lt;/code&gt; in the root of your Gatsby directory (next to &lt;code&gt;package.json&lt;/code&gt;). This is a sample of how this file should be:&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;// now.json&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// using version 2.0 of now.sh&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your Gatsby App Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alias&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yourdomain.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// remove it if you don't own a domain with now.sh&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;builds&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="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;package.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@now/static-build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;config&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;distDir&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// default folder for Gatsby builds&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One more step and we are good. Go to your &lt;code&gt;package.json&lt;/code&gt; and add a new script called: &lt;code&gt;now-build&lt;/code&gt; which should basically point to &lt;code&gt;gatsby build&lt;/code&gt; like this:&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;// package.json&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gatsby develop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;now-build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gatsby build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// other scripts ....&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are all set. Now you can simply run the command below in your Gatsby root folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;now --target production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will prepare a new build and deploy your Gatsby app into your domain with Now.sh. Life is beautiful!&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Github
&lt;/h2&gt;

&lt;p&gt;Well yes, it's a great idea to use Github editor to write a new blog post or just edit the previous posts and Now.sh can trigger a new deployment immediately after every new commit. The rule of the thumb here is that if you already did set an Alias to your domain, every commit to master branch of your Github will trigger a deployment to your website URL and other branches will only deploy a version to a new address. This address is accessible inside your Github Environment tab or in your Now.sh dashboard.&lt;/p&gt;

&lt;p&gt;In order to do it using Github you need to first &lt;a href="https://zeit.co/docs/v2/integrations/now-for-github/"&gt;connect your Github account&lt;/a&gt; to Now.sh. Afterward, all we need is to add a &lt;code&gt;now.json&lt;/code&gt; file similar to the previous step:&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;// now.json&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// using version 2.0 of now.sh&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your Gatsby App Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alias&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yourdomain.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// remove it if you don't own a domain with now.sh&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;builds&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="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;package.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@now/static-build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;config&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;distDir&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// default folder for Gatsby builds&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also make sure to add &lt;code&gt;now-build&lt;/code&gt; script to your &lt;code&gt;package.json&lt;/code&gt; file:&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;// package.json&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gatsby develop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;now-build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gatsby build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// other scripts ....&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;from now on, every commit to the master branch of your Github will trigger a deployment to your website URL. Great job, you're not a lazy developer!&lt;/p&gt;

&lt;p&gt;This post is originally written for my personal blog &lt;a href="https://fsociety.at"&gt;fsociety&lt;/a&gt; 🙃&lt;/p&gt;

</description>
      <category>gatsby</category>
      <category>deploy</category>
      <category>zeit</category>
      <category>react</category>
    </item>
  </channel>
</rss>
