<?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: Salvador Hernandez</title>
    <description>The latest articles on DEV Community by Salvador Hernandez (@salhernandez).</description>
    <link>https://dev.to/salhernandez</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%2F71946%2Fe913aeed-735e-46f3-9198-b26bde70461a.jpeg</url>
      <title>DEV Community: Salvador Hernandez</title>
      <link>https://dev.to/salhernandez</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/salhernandez"/>
    <language>en</language>
    <item>
      <title>Provide better time estimations with PERTify📈</title>
      <dc:creator>Salvador Hernandez</dc:creator>
      <pubDate>Sat, 23 Jan 2021 22:09:50 +0000</pubDate>
      <link>https://dev.to/salhernandez/provide-better-time-estimations-with-pertify-3kmk</link>
      <guid>https://dev.to/salhernandez/provide-better-time-estimations-with-pertify-3kmk</guid>
      <description>&lt;p&gt;As I was reading Robert Cecil Martin's &lt;a href="https://www.amazon.com/Clean-Coder-Conduct-Professional-Programmers/dp/0137081073" rel="noopener noreferrer"&gt;&lt;em&gt;The Clean Coder&lt;/em&gt;&lt;/a&gt; I stumbled upon a section in chapter 10 about estimating tasks. Using &lt;a href="https://en.wikipedia.org/wiki/Program_evaluation_and_review_technique" rel="noopener noreferrer"&gt;Project Evaluation and Review Technique (PERT)&lt;/a&gt; you can provide three values for a task: &lt;strong&gt;O&lt;/strong&gt;ptimal, &lt;strong&gt;N&lt;/strong&gt;ominal, and &lt;strong&gt;P&lt;/strong&gt;essimistic, and generate how long it was expected to finish a task. I wanted to try it out, but didn't want to write all the equations when being asked to provide estimates. I could have used any of the PERT calculators out there, but like a typical developer, I set out to create a tool that fitted my needs, hence &lt;a href="https://pertify.salhernandez.io/" rel="noopener noreferrer"&gt;PERTify&lt;/a&gt;. PERTify is hosted on AWS using &lt;a href="https://aws.amazon.com/cloudfront/" rel="noopener noreferrer"&gt;CloudFront&lt;/a&gt; and &lt;a href="https://aws.amazon.com/s3/" rel="noopener noreferrer"&gt;S3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This application is optimized for desktop screens!&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  PERT
&lt;/h1&gt;

&lt;p&gt;PERT is a statistical tool used in project management, which was designed to analyze and represent the tasks involved in completing a given project. The scheme provides a simple and effective way to convert estimates into probability distributions. For PERTify, we will be using tasks and subtasks, instead projects and tasks.&lt;/p&gt;

&lt;p&gt;For an in depth explanation of the calculations, please visit &lt;a href="https://codingjourneyman.com/2014/10/06/the-clean-coder-estimation/" rel="noopener noreferrer"&gt;The Clean Coder: Estimation&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Program_evaluation_and_review_technique" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;, and &lt;a href="https://www.linkedin.com/pulse/what-pert-how-can-we-use-dave-fourie-pmp-prince2-/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  PERTify
&lt;/h1&gt;

&lt;p&gt;For each row (&lt;strong&gt;subtask&lt;/strong&gt;) you will see the calculated probability distribution (&lt;strong&gt;μ&lt;/strong&gt;) and standard deviation of the probability distribution (&lt;strong&gt;σ&lt;/strong&gt;). &lt;strong&gt;σ&lt;/strong&gt; measures how uncertain the task is.&lt;br&gt;
At the top left of the card you will find &lt;strong&gt;μ sequence&lt;/strong&gt; which is the sum of all the subtasks' expected duration, and &lt;strong&gt;σ sequence&lt;/strong&gt; which is the standard deviation for all the subtasks.&lt;/p&gt;

&lt;p&gt;We will using hours as the unit of measurement.&lt;br&gt;
&lt;strong&gt;Alpha&lt;/strong&gt; is estimated to be done in 4.2 (&lt;strong&gt;μ&lt;/strong&gt;) hours. However, the estimated time to finish &lt;strong&gt;Alpha&lt;/strong&gt;, &lt;strong&gt;Beta&lt;/strong&gt;, and &lt;strong&gt;Gamma&lt;/strong&gt; is 14.2 (&lt;strong&gt;μ sequence&lt;/strong&gt;) hours with a standard deviation of 3.1 (&lt;strong&gt;σ sequence&lt;/strong&gt;) hours.&lt;/p&gt;

&lt;p&gt;Using the standard deviation we can calculate different estimates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;14.2 hours

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;μ sequence&lt;/strong&gt; + ( 0 * &lt;strong&gt;σ sequence&lt;/strong&gt; )&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;17.3 hours

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;μ sequence&lt;/strong&gt; + ( 1 * &lt;strong&gt;σ sequence&lt;/strong&gt; )&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;20.4 hours

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;μ sequence&lt;/strong&gt; + ( 2 * &lt;strong&gt;σ sequence&lt;/strong&gt; )&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The task is set to take 14.2 hours, or 17.3 hours, or 20.4 hours, etc... But will most likely take &lt;strong&gt;14 hours&lt;/strong&gt; after rounding down &lt;strong&gt;14.2&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Demo
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxiw86ib6i4ponxunc4t7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxiw86ib6i4ponxunc4t7.gif" alt="PERTify Demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What I learned
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;How to use 

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://material-ui.com/" rel="noopener noreferrer"&gt;Material-UI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devexpress.github.io/devextreme-reactive/react/grid/docs/guides/data-formatting/" rel="noopener noreferrer"&gt;DevExtreme React Grid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chrome.google.com/webstore/detail/tag-assistant-by-google/kejbdjndbnbjgmefkgdddjlbokphdefk" rel="noopener noreferrer"&gt;Tag Assistant Chrome Extension to Debug Google Analytics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://analytics.google.com/" rel="noopener noreferrer"&gt;Google Analytics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Links
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/salhernandez/pertify" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pertify.salhernandez.io/" rel="noopener noreferrer"&gt;PERTify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codingjourneyman.com/2014/10/06/the-clean-coder-estimation/" rel="noopener noreferrer"&gt;The Clean Coder: Estimation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Program_evaluation_and_review_technique" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/pulse/what-pert-how-can-we-use-dave-fourie-pmp-prince2-/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is your favorite Task Estimation tool? Let me know in the comments!&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>productivity</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Emojify 🦕 text of a webpage with a Chrome Extension</title>
      <dc:creator>Salvador Hernandez</dc:creator>
      <pubDate>Fri, 27 Nov 2020 05:06:49 +0000</pubDate>
      <link>https://dev.to/salhernandez/emojify-text-of-a-webpage-with-a-chrome-extension-5gc4</link>
      <guid>https://dev.to/salhernandez/emojify-text-of-a-webpage-with-a-chrome-extension-5gc4</guid>
      <description>&lt;p&gt;Ever wondered what would happen if you replaced all the words of a webpage with their emoji equivalent, like &lt;code&gt;t-rex&lt;/code&gt; replaced with 🦖, and &lt;code&gt;dolphin&lt;/code&gt; replaced with 🐬? Well look no further, I've created this Chrome Extension so you don't have to.&lt;/p&gt;

&lt;p&gt;Visit the repository for usage and installation instructions: &lt;a href="https://github.com/salhernandez/emojify" rel="noopener noreferrer"&gt;Emojify Repository&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Demo
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7hz5jpnc5y8bq1rlgin0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7hz5jpnc5y8bq1rlgin0.gif" alt="emojify demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Chrome Extension replaces single word emojis in the &lt;code&gt;p&lt;/code&gt;, &lt;code&gt;h1&lt;/code&gt;, &lt;code&gt;h2&lt;/code&gt;, &lt;code&gt;h3&lt;/code&gt;, &lt;code&gt;h4&lt;/code&gt;, &lt;code&gt;h5&lt;/code&gt; and &lt;code&gt;h6&lt;/code&gt; tags.&lt;/p&gt;

&lt;h1&gt;
  
  
  Resources needed to complete project
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;List of emojis and their aliases

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/github/gemoji/blob/master/db/emoji.json" rel="noopener noreferrer"&gt;https://github.com/github/gemoji/blob/master/db/emoji.json&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;a href="https://developer.chrome.com/apps/storage" rel="noopener noreferrer"&gt;Chrome Storage API&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://developer.chrome.com/extensions/tabs" rel="noopener noreferrer"&gt;Chrome Tabs API&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Containerize branches from React Application using ReactBranchContainer</title>
      <dc:creator>Salvador Hernandez</dc:creator>
      <pubDate>Sat, 31 Oct 2020 19:20:48 +0000</pubDate>
      <link>https://dev.to/salhernandez/containerize-branches-from-react-application-using-reactbranchcontainer-4ah5</link>
      <guid>https://dev.to/salhernandez/containerize-branches-from-react-application-using-reactbranchcontainer-4ah5</guid>
      <description>&lt;p&gt;When I'm developing a &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; Application and want to compare the output of the current work with another branch like &lt;code&gt;develop&lt;/code&gt; on my local I have to go through a series of time-consuming steps to get &lt;code&gt;develop&lt;/code&gt; branch up and running. Because of this &lt;a href="https://github.com/salhernandez/ReactBranchContainer" rel="noopener noreferrer"&gt;ReactBranchContainer&lt;/a&gt; was born.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps without &lt;strong&gt;ReactBranchContainer&lt;/strong&gt;:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Stash local changes with &lt;code&gt;git stash&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Checkout &lt;code&gt;develop&lt;/code&gt; branch with &lt;code&gt;git checkout develop&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Re-install dependencies &lt;code&gt;npm install&lt;/code&gt;

&lt;ol&gt;
&lt;li&gt;Re-install dependencies when using new libraries&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;When using &lt;a href="https://sass-lang.com/" rel="noopener noreferrer"&gt;SASS&lt;/a&gt;: Generate CSS from SCSS files with &lt;code&gt;npm run css&lt;/code&gt;
&lt;/li&gt;

&lt;li&gt;Run application &lt;code&gt;npm run start&lt;/code&gt;
&lt;/li&gt;

&lt;li&gt;Go to &lt;code&gt;localhost:3000&lt;/code&gt; to see output &lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;I embarked on a journey to create a tool that would allow me to keep run the application with the use of &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;, &lt;a href="https://docs.docker.com/engine/reference/builder/" rel="noopener noreferrer"&gt;Dockerfile&lt;/a&gt;, &lt;a href="https://docs.docker.com/compose/compose-file/" rel="noopener noreferrer"&gt;Docker-Compose&lt;/a&gt; and a &lt;code&gt;bash&lt;/code&gt; script. Now I can compare my current work with another branch side-by-side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps with &lt;strong&gt;ReactBranchContainer&lt;/strong&gt;:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;./rbc.sh -b develop&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Go to &lt;code&gt;localhost:5000&lt;/code&gt; to see output&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Demo
&lt;/h1&gt;

&lt;p&gt;Left window is watching for latest code changes and serving them on &lt;code&gt;localhost:3000&lt;/code&gt; and right window is running a Docker container with &lt;code&gt;develop&lt;/code&gt; branch on &lt;code&gt;localhost:5000&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftxxmup25ljnm79e8vh7z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftxxmup25ljnm79e8vh7z.gif" alt="ReactBranchContainerExample"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I spent many hours creating a tool that alleviates a 5 minute problem. Is the Remedy worst than the decease? Maybe. Did I have fun learning about Docker? Yes. Am I a Docker know-it-all? No.&lt;/p&gt;
&lt;h1&gt;
  
  
  What I learned
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;How to add Private SSH Key to &lt;a href="https://hub.docker.com/_/node" rel="noopener noreferrer"&gt;Node Docker Image&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;How to pass build arguments(&lt;code&gt;--build-arg&lt;/code&gt;, &lt;code&gt;ARG&lt;/code&gt;) from &lt;code&gt;docker-compose.yml&lt;/code&gt; to &lt;code&gt;.Dockerfile&lt;/code&gt; 

&lt;ul&gt;
&lt;li&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgfcqylamt2c3zvp3aqku.png" alt="Alt Text"&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;How to access environment variables in &lt;code&gt;docker-compose.yml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;How to containerize a React Application in a Docker image&lt;/li&gt;
&lt;li&gt;How to accept flags in bash script with &lt;a href="[https://link](https://linuxconfig.org/how-to-use-getopts-to-parse-a-script-options)"&gt;&lt;code&gt;getopts&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  How to use it
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Before using it, you need to update &lt;code&gt;rbc.sh&lt;/code&gt;  with the proper variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;REPOSITORY_URL&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Contains the SSH URL to your repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PROJECT_NAME&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Name of the project (&lt;strong&gt;name of repository&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BRANCH_NAME&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Branch to build&lt;/li&gt;
&lt;li&gt;Defaults to &lt;code&gt;develop&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NODE_VERSION_REACT_APP&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Node version used to develop React Application&lt;/li&gt;
&lt;li&gt;Defaults to &lt;code&gt;latest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;This is used to create pull correct image: &lt;code&gt;node:latest&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LOCAL_PORT&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Port used by host&lt;/li&gt;
&lt;li&gt;Defaults to &lt;code&gt;5000&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;REACT_CONTAINER_PORT&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Port used by react application&lt;/li&gt;
&lt;li&gt;Defaults to &lt;code&gt;3000&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ID_RSA_PATH&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;path to SSH RSA Key
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Project Information&lt;/span&gt;
&lt;span class="nv"&gt;REPOSITORY_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"git@github.com:salhernandez/test-react.git"&lt;/span&gt;
&lt;span class="nv"&gt;PROJECT_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"test-react"&lt;/span&gt;
&lt;span class="nv"&gt;BRANCH_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"develop"&lt;/span&gt;
&lt;span class="nv"&gt;NODE_VERSION_REACT_APP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"latest"&lt;/span&gt;

&lt;span class="c"&gt;# default create-react-app port&lt;/span&gt;
&lt;span class="nv"&gt;REACT_CONTAINER_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3000
&lt;span class="nv"&gt;LOCAL_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5000

&lt;span class="c"&gt;# path to SSH RSA KEY&lt;/span&gt;
&lt;span class="nv"&gt;ID_RSA_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/c/Users/User/.ssh/id_rsa"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;rbc.sh&lt;/code&gt; will copy the SSH key into the container and use it to pull the repository.&lt;/p&gt;
&lt;h2&gt;
  
  
  Run it
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# run with defaults&lt;/span&gt;
./rbc.sh
&lt;span class="c"&gt;# access application via localhost:5000&lt;/span&gt;

&lt;span class="c"&gt;# run with a specific branch&lt;/span&gt;
./rbc.sh &lt;span class="nt"&gt;-b&lt;/span&gt; bug-fix
&lt;span class="c"&gt;# access application via localhost:5000&lt;/span&gt;

&lt;span class="c"&gt;# run with a specific branch and set local port&lt;/span&gt;
./rbc.sh &lt;span class="nt"&gt;-b&lt;/span&gt; bug-fix &lt;span class="nt"&gt;-p&lt;/span&gt; 4001
&lt;span class="c"&gt;# access application via localhost:4001&lt;/span&gt;

&lt;span class="c"&gt;# run with a specific branch, set local port and container port&lt;/span&gt;
./rbc.sh &lt;span class="nt"&gt;-b&lt;/span&gt; bug-fix &lt;span class="nt"&gt;-p&lt;/span&gt; 4001 &lt;span class="nt"&gt;-c&lt;/span&gt; 3001
&lt;span class="c"&gt;# access application via localhost:4001 &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Under the hood
&lt;/h1&gt;
&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account" rel="noopener noreferrer"&gt;Working SSH private key that has access to your GitHub account&lt;/a&gt;

&lt;ol&gt;
&lt;li&gt;This can also be configured for other remotes&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/get-docker/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="[https://](https://en.wikipedia.org/wiki/Bash_(Unix_shell))link"&gt;Bash Shell&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;rbc.sh&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;BRANCH_NAME, PROJECT_NAME, REPOSITORY_URL, REACT_CONTAINER_PORT, and ID_RSA_PATH&lt;/code&gt; are passed into &lt;code&gt;docker-compose build&lt;/code&gt; as &lt;a href="https://docs.docker.com/compose/reference/build/" rel="noopener noreferrer"&gt;build-time variables&lt;/a&gt;(&lt;code&gt;--build-arg&lt;/code&gt;) and &lt;code&gt;IMAGE_NAME&lt;/code&gt; is added as an &lt;strong&gt;environment variable&lt;/strong&gt; with a value of &lt;code&gt;${PROJECT_NAME}/${BRANCH_NAME}:latest&lt;/code&gt; which translates to &lt;code&gt;test-react/develop:latest&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# build image&lt;/span&gt;
docker-compose build &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;$BUILD_CACHE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;BRANCH_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;PROJECT_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PROJECT_NAME&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;REPOSITORY_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REPOSITORY_URL&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;REACT_CONTAINER_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REACT_CONTAINER_PORT&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;NODE_VERSION_REACT_APP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$NODE_VERSION_REACT_APP&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;SSH_PRIVATE_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ID_RSA_PATH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# translates to &lt;/span&gt;
docker-compose build &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;$BUILD_CACHE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;BRANCH_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"develop"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;PROJECT_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"test-react"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;REPOSITORY_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"git@github.com:salhernandez/test-react.git"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;REACT_CONTAINER_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3000 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;NODE_VERSION_REACT_APP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"latest"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;SSH_PRIVATE_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /c/Users/User/.ssh/id_rsa&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the image is built, it will be tagged with the name &lt;code&gt;test-react/develop:latest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then it runs the image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# in interactive mode&lt;/span&gt;
docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$LOCAL_PORT&lt;/span&gt;:&lt;span class="nv"&gt;$REACT_CONTAINER_PORT&lt;/span&gt; &lt;span class="nv"&gt;$IMAGE_NAME&lt;/span&gt;

&lt;span class="c"&gt;# translates to&lt;/span&gt;
docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 5000:3000 test-react/develop:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;docker-compose.yml&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;BRANCH_NAME, PROJECT_NAME, REPOSITORY_URL, REACT_CONTAINER_PORT, and SSH_PRIVATE_KEY&lt;/code&gt; are passed into &lt;code&gt;.Dockerfile&lt;/code&gt; as &lt;a href="https://docs.docker.com/engine/reference/builder/#arg" rel="noopener noreferrer"&gt;build-time variables&lt;/a&gt;(&lt;code&gt;ARG&lt;/code&gt;). Image will have the name defined by &lt;strong&gt;environment variable &lt;code&gt;IMAGE_NAME&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;version: '3.7'
services:
  the_container:
    image: ${IMAGE_NAME} # environment variable
    build:
      context: ./
      dockerfile: .Dockerfile
      args:
        BRANCH_NAME: ${BRANCH_NAME} # --build-arg
        PROJECT_NAME: ${PROJECT_NAME} # --build-arg
        REPOSITORY_URL: ${REPOSITORY_URL} # --build-arg
        REACT_CONTAINER_PORT: ${REACT_CONTAINER_PORT} # --build-arg
        NODE_VERSION_REACT_APP: ${NODE_VERSION_REACT_APP} # --build-arg
        SSH_PRIVATE_KEY: ${SSH_PRIVATE_KEY} # --build-arg
    stdin_open: true

&lt;span class="c"&gt;# translates to&lt;/span&gt;
version: '3.7'
services:
  the_container:
    image: test-react/develop:latest &lt;span class="c"&gt;# environment variable&lt;/span&gt;
    build:
      context: ./
      dockerfile: .Dockerfile
      args:
        BRANCH_NAME: develop &lt;span class="c"&gt;# --build-arg&lt;/span&gt;
        PROJECT_NAME: test-react &lt;span class="c"&gt;# --build-arg&lt;/span&gt;
        REPOSITORY_URL: git@github.com:salhernandez/test-react.git &lt;span class="c"&gt;# --build-arg&lt;/span&gt;
        REACT_CONTAINER_PORT: 3000 &lt;span class="c"&gt;# --build-arg&lt;/span&gt;
        NODE_VERSION_REACT_APP: latest &lt;span class="c"&gt;# --build-arg&lt;/span&gt;
        SSH_PRIVATE_KEY: &amp;lt;private_key&amp;gt; # --build-arg
    stdin_open: true

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;.Dockerfile&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Using &lt;code&gt;ARG&lt;/code&gt;s the dockerfile does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Uses &lt;code&gt;node:&amp;lt;NODE_VERSION_REACT_APP&amp;gt;&lt;/code&gt; as base image&lt;/li&gt;
&lt;li&gt;Sets &lt;code&gt;ARG&lt;/code&gt;s&lt;/li&gt;
&lt;li&gt;Sets &lt;a href="https://docs.docker.com/engine/reference/builder/#workdir" rel="noopener noreferrer"&gt;working directory&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Copies SSH RSA key into the container&lt;/li&gt;
&lt;li&gt;Clones repository from &lt;code&gt;REPOSITORY_URL&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Sets working directory again, but now it is based on the project folder cloned&lt;/li&gt;
&lt;li&gt;Installs dependencies&lt;/li&gt;
&lt;li&gt;Removes SSH key&lt;/li&gt;
&lt;li&gt;Exposes port to be used by the application: &lt;code&gt;REACT_CONTAINER_PORT&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Runs the application with &lt;code&gt;npm start&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# latest version of Node.js&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; NODE_VERSION_REACT_APP="latest"&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; DOCKER_NODE_IMAGE="node:${NODE_VERSION_REACT_APP}"&lt;/span&gt;

&lt;span class="c"&gt;# Builds from node image, defaults to node:latest&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; "${DOCKER_NODE_IMAGE}"&lt;/span&gt;

&lt;span class="c"&gt;# Will only be used once&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; SSH_PRIVATE_KEY=0&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BRANCH_NAME=0&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; REPOSITORY_URL=0&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; PROJECT_NAME=0&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; REACT_CONTAINER_PORT=3000&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BASE_WORKDIR="/app"&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; PROJECT_WORKDIR="${BASE_WORKDIR}/${PROJECT_NAME}"&lt;/span&gt;

&lt;span class="c"&gt;# Set working directory&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; "${BASE_WORKDIR}"&lt;/span&gt;

&lt;span class="c"&gt;# Setup SSH&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/.ssh/
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SSH_PRIVATE_KEY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/.ssh/id_rsa

&lt;span class="c"&gt;# Make sure your domain is accepted&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;ssh-keyscan github.com &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.ssh/known_hosts
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;0600 ~/.ssh/id_rsa

&lt;span class="c"&gt;# Clone repository via SSH&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;git clone &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REPOSITORY_URL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Set working directory again, now we're inside the react project itself&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; "${PROJECT_WORKDIR}"&lt;/span&gt;

&lt;span class="c"&gt;# Get all branches from remote&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;git fetch

&lt;span class="c"&gt;# Checkout branch&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;git checkout &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BRANCH_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;react-scripts

&lt;span class="c"&gt;# Remove SSH KEY&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ~/.ssh/

&lt;span class="c"&gt;# Expose port which is used by the actual application&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; $REACT_CONTAINER_PORT&lt;/span&gt;

&lt;span class="c"&gt;# Finally runs the application&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; [ "npm", "start" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;code&gt;rbc.sh&lt;/code&gt; runs two commands, one to build the image, and one to run it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# build image&lt;/span&gt;
docker-compose build \
$BUILD_CACHE \
--build-arg BRANCH_NAME=$BRANCH_NAME \
--build-arg PROJECT_NAME=$PROJECT_NAME \
--build-arg REPOSITORY_URL=$REPOSITORY_URL \
--build-arg REACT_CONTAINER_PORT=$REACT_CONTAINER_PORT \
--build-arg NODE_VERSION_REACT_APP=$NODE_VERSION_REACT_APP \
--build-arg SSH_PRIVATE_KEY="$(cat ${ID_RSA_PATH})"

# run image
docker run -it --rm -p $LOCAL_PORT:$REACT_CONTAINER_PORT $IMAGE_NAME

&lt;span class="c"&gt;# go to localhost:5000 to see the live react app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Warning!
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;DO NOT USE THIS TO PUSH AN IMAGE TO DOCKER HUB! If you run &lt;code&gt;docker history &amp;lt;image_name&amp;gt; --no-trunc&lt;/code&gt;  you will see all the variables passed into the image like your ID_RSA token! This should only be used for development purposes only! More information [here].(&lt;a href="https://docs.docker.com/engine/reference/commandline/history/" rel="noopener noreferrer"&gt;https://docs.docker.com/engine/reference/commandline/history/&lt;/a&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a more secure way to pass build secret information use &lt;a href="https://github.com/moby/buildkit" rel="noopener noreferrer"&gt;BuildKit&lt;/a&gt;: &lt;a href="https://docs.docker.com/develop/develop-images/build_enhancements/#new-docker-build-secret-information" rel="noopener noreferrer"&gt;New Docker Build secret information&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/moby/buildkit#quick-start" rel="noopener noreferrer"&gt;BuildKit is still experimental and not supported by Windows&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Useful information
&lt;/h1&gt;

&lt;p&gt;Since this will be generating new containers, you will want to clean up intermediate and unused containers every now and then, use the following commands to help you free up some space:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/engine/reference/commandline/system_prune/" rel="noopener noreferrer"&gt;Docker provides a single command that will clean up any resources&lt;/a&gt; — images, containers, volumes, and networks — that are dangling (not associated with a container):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker system prune
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To additionally remove any stopped containers and all unused images (not just dangling images), add the &lt;code&gt;a&lt;/code&gt; flag to the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker system prune -a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Helpful URLs
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="[https://link](https://vsupalov.com/docker-arg-env-variable-guide/)"&gt;Docker ARG, ENV and .env - a Complete Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://linuxconfig.org/how-to-use-getopts-to-parse-a-script-options" rel="noopener noreferrer"&gt;&lt;code&gt;getops&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vsupalov.com/build-docker-image-clone-private-repo-ssh-key/" rel="noopener noreferrer"&gt;Access Private Repositories from Your Dockerfile Without Leaving Behind Your SSH Keys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/paperchain/fetching-private-github-repos-from-a-docker-container-273f25ec5a74" rel="noopener noreferrer"&gt;Fetching private GitHub repos from a Docker container&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Checkout the project on &lt;a href="https://github.com/salhernandez/ReactBranchContainer" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Q&amp;amp;A
&lt;/h1&gt;

&lt;p&gt;What problem did you try to fix with a tool/project because you did not want repeat a series of tasks?&lt;/p&gt;

</description>
      <category>docker</category>
      <category>bash</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Get Screenshot + Console Logs + HAR log using Capture Page State Chrome Extension</title>
      <dc:creator>Salvador Hernandez</dc:creator>
      <pubDate>Fri, 27 Dec 2019 07:05:27 +0000</pubDate>
      <link>https://dev.to/salhernandez/get-screenshot-console-logs-har-log-using-capture-page-state-chrome-extension-4ona</link>
      <guid>https://dev.to/salhernandez/get-screenshot-console-logs-har-log-using-capture-page-state-chrome-extension-4ona</guid>
      <description>&lt;h1&gt;
  
  
  What Problem do I want to solve?
&lt;/h1&gt;

&lt;p&gt;As a developer whenever a bug is reported you want to have as much context as possible to be able to solve the issue in the most efficient manner. Depending on the technical level of the reporter, you can get a screenshot with reproduction steps, or maybe just a screenshot with no context. If the error happens on a web app it can be caused by many things...logic from the front-end may have failed, the network may have gone down, the back-end did not respond in time, or there was a server error. Many things could have gone wrong which is why providing as much context as possible is important when trying to squash a bug. As developers, we check the console logs in the Developer Tools to look for errors or look at the Network tab to check if any of the requests returned an error or timed out. If there was a tool that allowed you to get all three: &lt;em&gt;Screenshot&lt;/em&gt;, Network requests aka &lt;em&gt;HAR log&lt;/em&gt;, and &lt;em&gt;Console Logs&lt;/em&gt; at once, it would make all developers' lives easier by providing as much context as possible.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why do I care about this?
&lt;/h1&gt;

&lt;p&gt;As a developer, when an issue is reported I find myself asking many questions that the reporter does not always have the answer to. Many of these questions can be solved by providing &lt;em&gt;HAR log&lt;/em&gt;, &lt;em&gt;Console Logs&lt;/em&gt;, and a &lt;em&gt;Screenshot&lt;/em&gt;. This will allow me to narrow down in which part of the application needs to be fixed and not spend much time trying to replicate the issue.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why create an extension to gather all of these if you can do it manually?
&lt;/h1&gt;

&lt;p&gt;Because it is time-consuming! and no one wants to read instructions when they're mad because the web app is not working properly and you're trying to report an issue.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to get each item individually
&lt;/h1&gt;

&lt;p&gt;If you are curious as to how to get each of the three items I will explain them below&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking Screenshot (using Snipping Tool)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open Snipping Tool&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;strong&gt;New&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Draw rectangle on capture region&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;strong&gt;Save Snip&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give it a name and click &lt;strong&gt;OK&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Getting Console logs(On Google Chrome)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open Chrome Dev Tools (&lt;strong&gt;F12&lt;/strong&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;strong&gt;Console&lt;/strong&gt; Tab&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Right Click inside of panel&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;strong&gt;Save as...&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give it a name and click &lt;strong&gt;Save&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Getting HAR log (On Google Chrome)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open Chrome Dev Tools (&lt;strong&gt;F12&lt;/strong&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;strong&gt;Network&lt;/strong&gt; Tab&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;strong&gt;Export HAR...&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give it a name and click &lt;strong&gt;Save&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  How to get Screenshot + Console Logs + HAR log using &lt;em&gt;Capture Page State&lt;/em&gt;
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Click on Extension Icon&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpgfy2soq2vnrjb47kbto.png" alt="Capture Page State Popup"&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Select what you want to capture&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Screenshot&lt;/li&gt;
&lt;li&gt; Console Logs&lt;/li&gt;
&lt;li&gt; HAR log

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Chrome Dev Tools needs to be open to get HAR log&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Click on &lt;strong&gt;Get Snapshot&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; The items selected will now be downloaded, 1 file per item&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h1&gt;
  
  
  Demo
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fsalhernandez%2FcapturePageState%2Fmaster%2Fassets%2FcapturePageState.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fsalhernandez%2FcapturePageState%2Fmaster%2Fassets%2FcapturePageState.gif" alt="Demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for your time, if you want to install or read more about &lt;em&gt;Capture Page State Chrome Extension&lt;/em&gt; you can &lt;a href="https://github.com/salhernandez/capturePageState" rel="noopener noreferrer"&gt;visit the repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>chrome</category>
      <category>javascript</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Introducing pomoDoNotDisturb</title>
      <dc:creator>Salvador Hernandez</dc:creator>
      <pubDate>Wed, 28 Aug 2019 05:20:37 +0000</pubDate>
      <link>https://dev.to/salhernandez/introducing-pomodonotdisturb-3io5</link>
      <guid>https://dev.to/salhernandez/introducing-pomodonotdisturb-3io5</guid>
      <description>&lt;p&gt;Not too long ago we got these signs at work:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2NSNOia2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images-na.ssl-images-amazon.com/images/I/71diVACOZhL._SL1500_.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2NSNOia2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images-na.ssl-images-amazon.com/images/I/71diVACOZhL._SL1500_.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Their purpose is to let co-workers know if you are available to chat or not. I liked the idea, but it was a hassle having to reach for the sign and change it. Also, since the sign is not within my field of view, I would sometimes forget what the sign was set for and would have to check. I thought that there should be a better way of handling this where I could change my status on a hub similar to an Elgato Stream Deck and it could show my current status on a screen. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tNUJ4Q1---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images-na.ssl-images-amazon.com/images/I/81T5LcIMbKL._SL1500_.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tNUJ4Q1---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images-na.ssl-images-amazon.com/images/I/81T5LcIMbKL._SL1500_.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is how &lt;a href="https://github.com/salhernandez/pomoDoNotDisturb/"&gt;pomoDoNotDisturb&lt;/a&gt; was born. Since I use the Pomodoro method to focus on tasks, I figured that it would be nice if the hub could also include a timer that would let people know if I was available or not based on my Pomodoro status.&lt;/p&gt;

&lt;p&gt;The end result consisted of a Raspberry Pi Zero W that talks to a Raspberry Pi 3 via USB as a USB/Ethernet Gadget. The Pi Zero has a screen attached to it, while the Raspberry Pi has a touchscreen attached to it. The Raspberry Pi 3 runs Flask which serves two pages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;/hub

&lt;ol&gt;
&lt;li&gt;Controls the status and Pomodoro session&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;/status

&lt;ol&gt;
&lt;li&gt;Shows current status&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For more information please visit the Github repo: &lt;a href="https://github.com/salhernandez/pomoDoNotDisturb/"&gt;pomoDoNotDisturb&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The toughest part was making the Pi's talk to each other. It ended up being as simple as assigning static IPs to the USB connection.&lt;/p&gt;

&lt;p&gt;Feedback is welcomed! Leave a comment or open an issue.&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>python3</category>
      <category>flask</category>
      <category>socketio</category>
    </item>
    <item>
      <title>What do you do at the end of the workday?</title>
      <dc:creator>Salvador Hernandez</dc:creator>
      <pubDate>Tue, 05 Feb 2019 06:14:20 +0000</pubDate>
      <link>https://dev.to/salhernandez/what-do-you-do-at-the-end-of-the-workday-3bhd</link>
      <guid>https://dev.to/salhernandez/what-do-you-do-at-the-end-of-the-workday-3bhd</guid>
      <description>&lt;p&gt;As a Software Engineer what do you do at the end of the day?&lt;br&gt;
I want to start writing a summary about what I worked to document what I did well and what I can improve on such as responding to emails, communicating ideas, getting into the zone, etc...&lt;/p&gt;

&lt;p&gt;Do any of you have end-of-day habits/rituals that made you better at your craft?&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
  </channel>
</rss>
