<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by James Villarrubia on Medium]]></title>
        <description><![CDATA[Stories by James Villarrubia on Medium]]></description>
        <link>https://medium.com/@james_mtc?source=rss-6a0def09ab09------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*4ZE9_XKq4umdYtYY.jpg</url>
            <title>Stories by James Villarrubia on Medium</title>
            <link>https://medium.com/@james_mtc?source=rss-6a0def09ab09------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 01:57:50 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@james_mtc/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Unsucking Create React App Deployments]]></title>
            <link>https://medium.com/@james_mtc/unsucking-create-react-app-deployments-7f5dc80e1577?source=rss-6a0def09ab09------2</link>
            <guid isPermaLink="false">https://medium.com/p/7f5dc80e1577</guid>
            <category><![CDATA[npm]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[create-react-app]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[devops]]></category>
            <dc:creator><![CDATA[James Villarrubia]]></dc:creator>
            <pubDate>Mon, 17 Jun 2019 19:53:42 GMT</pubDate>
            <atom:updated>2019-06-19T16:42:48.870Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/747/0*fPA_-7UnDeBUMyTR.jpg" /></figure><h3>Unsucking Create-React-App Deployments</h3><p>So you want to deploy a create-react-app? Cool throw it in an S3 bucket. But wait, you want to put it <em>behind a domain name</em>? Okay well set up Route53 and then mount the bucket. Hold on, what about SSL certs? And auto-invalidations on deployment? And setting up QA environments for your testers?</p><p>30 hours later…</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FIi4dvuRs9WSCszbCcF%2Ftwitter%2Fiframe&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FIi4dvuRs9WSCszbCcF%2Fsource.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FIi4dvuRs9WSCszbCcF%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="211" frameborder="0" scrolling="no"><a href="https://medium.com/media/0e3448831985a864dc9e75d3b02ee377/href">https://medium.com/media/0e3448831985a864dc9e75d3b02ee377/href</a></iframe><p>Every time I deploy a CRA app, I end up using the same deployment scripts and npm script hacks. They’ve become so universally used on my teams that every stack starts with copying and pasting those command and scripts into a folder. So I thought… why not share it with the world!</p><p>ENTER…. <a href="https://www.npmjs.com/package/stackpack">stackpack</a></p><p><strong><em>Stackpack is dev-dependency (or global) that you can throw into your CRA or serverless express.js lambda (soon) or express.js Beanstalk (soon) and it will create an opinionated DevOps setup for you in minutes.</em></strong></p><p>Yeah. Prototype to multi-env setup <strong><em>in minutes.</em></strong></p><h3><strong>How does it work?</strong></h3><p>Stackpack abstracts out lots of the AWS cli commands and provides you with basic templates that connect Cloudfront, S3, Route53, etc. All you have to do is run npm run deploy:develop and it will build and deploy your changes to S3 and invalidate your cache. If you use Gitlab’s runners, you can also just hit npm run git:develop or git:qaand it will commit your changes, merge up a branch in GitFlow, and tag the right version number on master.</p><h3><strong>But this seems very opinionated… why?</strong></h3><p>Because most frontend developers trying to do DevOps on their own don’t actually care. They want it to work in production, and they want it to work today. That’s why my teams have used it, and that’s why we liked it. Quick, easy, replicable deployment. All of our environments follow the same basic gitflow and deployment principles:</p><ol><li>Git commits must go from Feature&gt;Develop&gt;QA&gt;Staging/Demo&gt;Production</li><li>All apps are rebuilt entirely in uniform docker containers during deployment. This applies from CRA to Lambda to backend to Python scripts, etc. We trust NO local environments.</li><li>We use the same tools for almost everything (node, React, Redux, AWS etc.). Common stack means no DevOps headaches every time a new stack gets added.</li></ol><p>So that’s the “why.” Let’s get into the what…</p><h3>The Tutorial</h3><p>First setup a create-react-app</p><pre>npx create-react-app awesome-app<br>cd awesome-ap<br>touch .env<br>npm start</pre><p>Now let’s install the stackpack library</p><pre>npm install --save-dev stackpack</pre><p>Let’s use the default S3 Cloudfront SSL based template…</p><pre>stackpack init s3-cf-https</pre><pre># if you are using gitlab runners: <br>stackpack init s3-cf-https-gitlab </pre><p>…and make sure we have the right git branches set up to use our version of git-flow.</p><pre>git init; git branch develop; git branch qa; git branch staging;<br>stackpack init gitflow;</pre><p>Now open up package.json to make just couple config edits.</p><p><strong>FIRST:</strong> Setup the domain name you want to use for this app in route53 and add it to &quot;domain&quot;:&quot;www.example.com&quot; . In this example, I’ve used <a href="http://www.awesomeapp.com./">www.awesomeapp.com.</a> Subsequent environments will be referenced as develop-www.awesomeapp.com or qa-www.awesomeapp.com. These are the domains that you are allowed to point to from Route53 to the respective CloudFront domain endpoint.</p><p><strong>SECOND: </strong>If you have an SSL certificate in AWS, replace the default in the stackpack settings like&quot;ssl&quot;:&quot;arn:aws:acm:us-east-1LXXXXXXXXXX&quot;. Otherwise, just delete the ssl property.</p><p><strong>THIRD:</strong> If you want to use a different AWS IAM user to deploy that isn’t just your default, then replace &quot;profile&quot;:&quot;default&quot; with the right profile name. This is helpful for using Gitlab runners with a separate AWS profile. For security, we set up a restricted runner profile for every stack with limited permissions.</p><p><strong>FOURTH: </strong>If you don’t want to use CloudFront on every environment, you should remove those environment names from the cf_envs array. This array must be a subset of the environments array. These endpoints will be exposed without https and may have some hiccups, just FYI.</p><p>Next, we’re going to initiate some templated CloudFront configs. HINT: You can update these in the .stackpack/ to customize them, then run stackpack cf update to push the changes to AWS.</p><pre>stackpack cf setup</pre><p>Which should run and then show you…</p><pre>Refreshing local Cloudfront configs…<br>   refreshing… develop<br>   refreshing… qa<br>   refreshing… staging<br>   refreshing… prod<br>   Refreshing and Creation is complete.</pre><p><em>Now you are ready to deploy!</em></p><p><em>Really. I swear.</em></p><p>There are npm scripts that have been added that you can use to do these things together. But we’re going to take it one step at a time.</p><pre>stackpack build --env develop;<br>stackpack deploy --env develop;<br>stackpack cf invalidate --env develop;</pre><p>The build step runs react-scripts builds . The deploy step moves it to the S3 bucket. The invalidate step runs a generic /* invalidation on CloudFront.</p><p>Annnnnnnnd you’re done.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2F3o7btNa0RUYa5E7iiQ%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fgiphy.com%2Fgifs%2Flatenightseth-boom-3o7btNa0RUYa5E7iiQ&amp;image=https%3A%2F%2Fmedia3.giphy.com%2Fmedia%2F3o7btNa0RUYa5E7iiQ%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="435" frameborder="0" scrolling="no"><a href="https://medium.com/media/e60437ef6787036fe1cb2777105a1717/href">https://medium.com/media/e60437ef6787036fe1cb2777105a1717/href</a></iframe><p>Feel free to comment, below! Next up in the stackpack lineup, I’m going to deploy a <a href="https://github.com/jaredpalmer/razzle">Razzle app</a> serverside app via Lambda and some hidden serverless magic.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7f5dc80e1577" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to unsuck AWS Lambda’s native compilation for NodeJS functions (with Docker and Bash)]]></title>
            <link>https://medium.com/@james_mtc/how-to-unsuck-aws-lambdas-native-compilation-for-nodejs-functions-with-docker-and-bash-5301a26a19b1?source=rss-6a0def09ab09------2</link>
            <guid isPermaLink="false">https://medium.com/p/5301a26a19b1</guid>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[node]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[aws-lambda]]></category>
            <dc:creator><![CDATA[James Villarrubia]]></dc:creator>
            <pubDate>Sat, 13 May 2017 14:06:53 GMT</pubDate>
            <atom:updated>2018-02-21T04:34:16.507Z</atom:updated>
            <content:encoded><![CDATA[<p>I just wanted to write a lambda function.</p><p>That’s it. Just one EASY function. And put it on Lambda, behind a gateway API call. But AWS-lambda has this nasty quirk that native code modules need to be compiled in the exact same environment. I was using Claudia.js (while I had many options) to automate the upload to AWS. Claudia is great because it also handles the API-gateway creation.</p><p>But, despite all the magic of Claudia.js, I kept getting the bug:</p><pre>{<br>  &quot;errorMessage&quot;: &quot;/var/task/node_modules/webworker-threads/build/Release/WebWorkerThreads.node: invalid ELF header&quot;,<br>  &quot;errorType&quot;: &quot;Error&quot;,<br>  &quot;stackTrace&quot;: [<br>    &quot;Module.load (module.js:487:32)&quot;,<br>    &quot;tryModuleLoad (module.js:446:12)&quot;,<br>    &quot;Function.Module._load (module.js:438:3)&quot;,<br>    &quot;Module.require (module.js:497:17)&quot;,<br>    &quot;require (internal/module.js:20:19)&quot;,<br>    &quot;bindings (/var/task/node_modules/bindings/bindings.js:76:44)&quot;,<br>    &quot;Object.&lt;anonymous&gt; (/var/task/node_modules/webworker-threads/index.js:1:105)&quot;,<br>    &quot;Module._compile (module.js:570:32)&quot;<br>  ]<br>}</pre><p>Even dropped it on stackoverflow: <a href="http://stackoverflow.com/questions/43690371/can-i-use-webworkers-in-aws-lambda-node-6-10">http://stackoverflow.com/questions/43690371/can-i-use-webworkers-in-aws-lambda-node-6-10</a></p><p>Which is where I learned of AWS’s issue with native compilation. If I compile a module locally (on OSX) and then use claudia or even manually load the package, the native modules (node-gyp in my case) will be compiled against OSX and included as a local package. Womp womp.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/290/1*qFVyCbDd8Vn7r87JxM6eeQ.jpeg" /></figure><p>Solution?<em> Create an exact(ish) match of the AWS-Lambda env locally and compile the code and THEN load it to AWS. </em>Simple enough, right?</p><p>Wrong. Wrong wrong wrong wrong.</p><p>I’m still somewhat of a Docker noob, but the published containers out there were very unfriendly in their documentation even for a senior dev. A lot of trial and error was required. <strong>Many diet cokes died to bring you this solution.</strong></p><p>I’m using my AWS-Lambda MultiEnvironment structure (see <a href="https://medium.com/@james_mtc/automating-lambda-across-multiple-environments-50f47fbf393d">https://medium.com/@james_mtc/automating-lambda-across-multiple-environments-50f47fbf393d</a>)</p><p>In my case, the “natural” module is the one that did me in because it uses node-gyp. First thing we’re gonna do is create a Dockerfile</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e81218db27e9b7e438b6a3b6794dd9d8/href">https://medium.com/media/e81218db27e9b7e438b6a3b6794dd9d8/href</a></iframe><p>This Dockerfile uses the LambCI lambda image, but with the node 6.10 build. Drop in your ENV AWS keys. Then it goes to root, runs npm install and then run claudia update. The command in package.json looks like:</p><pre>claudia update --cache-api-config</pre><p>And because I hate running the same commands over and over again as I test out the deployment, here’s my bash script to automate the process</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8d0af5895d0e6a062d830386548f5cb0/href">https://medium.com/media/8d0af5895d0e6a062d830386548f5cb0/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5301a26a19b1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to unsuck Jenkins when deploying multiple private repositories.]]></title>
            <link>https://medium.com/@james_mtc/how-to-unsuck-jenkins-when-deploying-multiple-private-repositories-eb5ff3f5357f?source=rss-6a0def09ab09------2</link>
            <guid isPermaLink="false">https://medium.com/p/eb5ff3f5357f</guid>
            <category><![CDATA[ssh]]></category>
            <category><![CDATA[continuous-integration]]></category>
            <category><![CDATA[github]]></category>
            <category><![CDATA[jenkins]]></category>
            <category><![CDATA[git]]></category>
            <dc:creator><![CDATA[James Villarrubia]]></dc:creator>
            <pubDate>Tue, 09 May 2017 02:22:35 GMT</pubDate>
            <atom:updated>2017-05-09T16:14:25.188Z</atom:updated>
            <content:encoded><![CDATA[<p>Let’s say you’ve got a project that involves 3 or 4 different private repositories. Maybe you’re working on a startup and don’t want to give away your secret sauce. Maybe you’ve got a microservice architecture and you’ve just split everything up into crazy sub projects. Maybe you’re just a terrible coder and left all your .env files in your repositories and don’t want to prune your git tree.</p><p>Whatevs. Doesn’t matter. This tutorial will help you unsuck the Github Jenkins multiple private repository disaster.</p><p>Now I’ve done this now multiple times. But every single time I did it <em>slightly</em> differently and ended up breaking it. This last time, I wrote down instructions for <em>myself</em>. But they seem worth sharing.</p><h3>Why?</h3><p>Github does not allow the same deploy key to be used in multiple repositories. So if you want to deploy two or three apps or repositories to the same machine, you have to come up with some SSH / RSA trickery.</p><p>For more info, see:</p><ul><li><a href="https://help.github.com/articles/error-key-already-in-use/">Error: Key already in use - User Documentation</a></li><li><a href="http://stackoverflow.com/questions/13225826/using-the-same-deploy-key-for-multiple-github-projects">Using the same deploy key for multiple github projects</a></li></ul><h3>Assumptions:</h3><ul><li>LAMP stack (for config)</li><li>Config through .conf files</li><li>Node.js service running on something <em>other </em>than port 80</li><li>Github.com for private repositories</li><li>Standard Jenkins install with a “jenkins” user</li><li>SSH and root access to your deployed machine.</li><li>Jenkins is running on the local deployed machine (obviously not true, but I’m gonna skip the scripted SSH crap)</li></ul><p>You are adding an app to a subdomain to <a href="http://www.example.com./">www.example.com.</a></p><ol><li>SSH in to the target machine.</li><li>Make the directory</li></ol><pre>mkdir var/www/html/sub1.example.com</pre><p>3. Go and edit the .conf file. Probably already have one as 000-default.conf. Copy that and save it as example.com.conf</p><pre>vim etc/apache2/sites-enabled/example.com.conf</pre><p>4. Add the following</p><pre>&lt;VirtualHost *:80&gt;<br>  ServerName sub1.example.com<br>  ServerAdmin webmaster@localhost<br>  DocumentRoot /var/www/html/sub1.example.com/public_html/<br>  &lt;Directory &quot;/var/www/html&quot;&gt;<br>     AllowOverride All<br>  &lt;/Directory&gt;<br>  ErrorLog ${APACHE_LOG_DIR}/error.log<br>  CustomLog ${APACHE_LOG_DIR}/access.log combined<br>&lt;/VirtualHost&gt;</pre><p>5. Restart and then sudo in as jenkins</p><pre>sudo apache2 service restart<br>sudo su jenkins<br>cd ~/.ssh/</pre><p>6. Should now be in: var/lib/jenkins/.ssh</p><p>7. Create the new key pair</p><pre>ssh-keygen -t rsa</pre><p>8. When prompted, name the key “sub1-rsa”</p><p>9. After completing the creation, copy the blob from sub1-rsa.pub</p><p>10. Copy the blob and paste it into the deploy keys set on github. For example, this would be at <a href="https://github.com/MYNAME/example.com/settings/keys">https://github.com/MYNAME/sub1.example.com/settings/key</a>s</p><p>11. Edit the ssh config file under jenkins</p><pre>vim ~/.ssh/config</pre><p>12. Add the following to the config. This shortcuts any ssh command to use a particular key when going to the listed host. It “tricks” github into a separate key with a nonsense github subdomain.</p><pre>Host sub1.github.com<br>    HostName       github.com<br>    User           git<br>    IdentityFile   ~/.ssh/sub1-rsa<br>    IdentitiesOnly yes</pre><p>13. Now to test it. Run:</p><pre>ssh -T sub1.github.com</pre><p>This should use the “fake” host of sub1.github.com and then go to github.com and swap in the sub1-rsa key to make the call.</p><p>14. Nowcd /var/www/html/sub1.example.com</p><p>15. Git and pull the repository.</p><pre>git clone git@sub1.github.com:MYNAME/sub1.example.com.git</pre><p>16. Boom, now you have a git folder inside that can be run and SHOULD be run by the jenkins user.</p><p>17. Rename the folder to public_html</p><p>18. Inside jenkins, check the “github Project” box and put in the name of the repository <a href="https://github.com/Team-Uniken/demos.uniken.com/">https://github.com/MYNAME/sub1.example.com/</a></p><p>19. Under source code management, select git. Then add repository url: git@sub1.github.com:MYNAME/sub1.example.com.git</p><p>20. Select “Build when a change is pushed to GitHub”</p><p>21. Execute Shell script will look something like this</p><pre>cd /var/www/html/sub1.example.com/public_html/<br>git pull</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=eb5ff3f5357f" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>