<?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: Rob Galanakis</title>
    <description>The latest articles on DEV Community by Rob Galanakis (@robgalanakis).</description>
    <link>https://dev.to/robgalanakis</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%2F385677%2F276849c3-f8a8-4504-b49c-e5534c84a897.jpeg</url>
      <title>DEV Community: Rob Galanakis</title>
      <link>https://dev.to/robgalanakis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/robgalanakis"/>
    <language>en</language>
    <item>
      <title>Makefile and Dotenv</title>
      <dc:creator>Rob Galanakis</dc:creator>
      <pubDate>Tue, 09 Jun 2020 12:00:00 +0000</pubDate>
      <link>https://dev.to/lithictech/makefile-and-dotenv-3361</link>
      <guid>https://dev.to/lithictech/makefile-and-dotenv-3361</guid>
      <description>&lt;p&gt;In this series on Makefiles, we've covered &lt;a href="https://lithic.tech/blog/2020-05/makefile-wildcards"&gt;how to use wildcards&lt;/a&gt; and &lt;a href="https://lithic.tech/blog/2020-05/makefile-apps"&gt;using application presets&lt;/a&gt; rather than having to pass in values.&lt;/p&gt;

&lt;p&gt;There's one more technique we use for controlling Makefiles:&lt;/p&gt;

&lt;h2&gt;
  
  
  Dotenv (.env files)
&lt;/h2&gt;

&lt;p&gt;We &lt;strong&gt;love love love&lt;/strong&gt; using &lt;code&gt;.env&lt;/code&gt; files to configure our applications. If you're not familiar with them, the gist is that they specify environment variable keys and values in a very simple file format. For example, to control the &lt;code&gt;LOG_LEVEL&lt;/code&gt; var, you can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LOG_LEVEL=info
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And then load that at application startup (most languages have some sort of &lt;code&gt;dotenv&lt;/code&gt; package for this).&lt;/p&gt;

&lt;p&gt;While our full configuration practices are a topic for another day, we have a few rules we use on all of our projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All configuration through environment variables (do not load files, do not talk to external stores)&lt;/li&gt;
&lt;li&gt;Always use &lt;code&gt;.env&lt;/code&gt; files.&lt;/li&gt;
&lt;li&gt;Never check in &lt;code&gt;.env&lt;/code&gt; files.&lt;/li&gt;
&lt;li&gt;Only have one &lt;code&gt;.env&lt;/code&gt; file (no cascading files based on environment).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.env&lt;/code&gt; takes precedence over values in the environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of these decisions are no doubt controversial, but the goal is that &lt;code&gt;.env&lt;/code&gt; files provide unambiguous, canonical storage of local environment variables, and non-local environments use whatever native mechanisms for injecting environment variables before starting the process (Heroku Config Vars, AWS Parameter Store hooked up to ECS, etc).&lt;/p&gt;

&lt;h2&gt;
  
  
  Make and .env
&lt;/h2&gt;

&lt;p&gt;This ".env is the canonical storage of local environment" is so easy and standard, we can even set up Make to use it!&lt;/p&gt;

&lt;p&gt;We put this block at the top of Makefile- it looks for a .env file, and if present, it will set Make variables from it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="k"&gt;ifneq&lt;/span&gt; &lt;span class="nv"&gt;(,$(wildcard ./.env))&lt;/span&gt;
    &lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="sx"&gt; .env&lt;/span&gt;
    &lt;span class="err"&gt;export&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Where is this useful? Well, let's say you want to connect to your local application's database. We can put that database URL into the &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL=postgres://appuser:pass@localhost:13005/myapp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;(We always run our databases through &lt;code&gt;docker-compose&lt;/code&gt; and use different ports for different projects- you won't ever go back to &lt;code&gt;:5432&lt;/code&gt; once you start doing it this way)&lt;/p&gt;

&lt;p&gt;Now in our Makefile, we can set up a target to connect via &lt;code&gt;psql&lt;/code&gt;. Note the &lt;code&gt;cmd-exists-%&lt;/code&gt; target from &lt;a href="https://lithic.tech/blog/2020-05/makefile-wildcards"&gt;last week&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="k"&gt;ifneq&lt;/span&gt; &lt;span class="nv"&gt;(,$(wildcard ./.env))&lt;/span&gt;
    &lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="sx"&gt; .env&lt;/span&gt;
    &lt;span class="err"&gt;export&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;

&lt;span class="nl"&gt;cmd-exists-%&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1 &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"ERROR: '&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;(*)' must be installed and available on your PATH."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;psql&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;cmd-exists-psql&lt;/span&gt;
    psql &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;${DATABASE_URL}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now run it from the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ make psql
 psql "postgres://appuser:pass@localhost:13005/myapp"
 psql (12.2, server 11.4 (Debian 11.4-1.pgdg90+1))
 Type "help" for help.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Docker too!
&lt;/h2&gt;

&lt;p&gt;One more nice thing for this super-flexible &lt;code&gt;.env&lt;/code&gt; file! Docker and docker-compose can accept an &lt;code&gt;--env-file&lt;/code&gt; param, and by keeping everything in a single &lt;code&gt;.env&lt;/code&gt;, you can share all the same configuration between your local application, Make, and Docker build.&lt;/p&gt;

&lt;p&gt;Here's an adjusted Makefile snippet, and an example Docker command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="k"&gt;ifneq&lt;/span&gt; &lt;span class="nv"&gt;(,$(wildcard ./.env))&lt;/span&gt;
    &lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="sx"&gt; .env&lt;/span&gt;
    &lt;span class="err"&gt;export&lt;/span&gt;
    &lt;span class="nv"&gt;ENV_FILE_PARAM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;--env-file&lt;/span&gt; .env
&lt;span class="k"&gt;endif&lt;/span&gt;

&lt;span class="nl"&gt;docker-server&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$(PORT)&lt;/span&gt;:&lt;span class="nv"&gt;$(PORT)&lt;/span&gt; &lt;span class="nv"&gt;$(ENV_FILE_PARAM)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;$PORT&lt;/code&gt;, of course, is defined in the &lt;code&gt;.env&lt;/code&gt; file :)&lt;/p&gt;

&lt;h2&gt;
  
  
  More next time
&lt;/h2&gt;

&lt;p&gt;Later this week we'll talk about one more neat thing we do with Make to standardize even further. If you are writing any JavaScript in particular, it's life-changing.&lt;/p&gt;

&lt;p&gt;Finally, we'll wrap up this series in one week by talking about &lt;em&gt;why&lt;/em&gt; we are all-in on Make as a task runner (if we tried to sell you on it in the first post you probably would have ignored us).&lt;/p&gt;

</description>
      <category>make</category>
      <category>cli</category>
      <category>dotenv</category>
      <category>configuration</category>
    </item>
    <item>
      <title>Makefile Application Presets</title>
      <dc:creator>Rob Galanakis</dc:creator>
      <pubDate>Tue, 26 May 2020 13:30:21 +0000</pubDate>
      <link>https://dev.to/lithictech/makefile-application-presets-816</link>
      <guid>https://dev.to/lithictech/makefile-application-presets-816</guid>
      <description>&lt;p&gt;We saw in the &lt;a href="https://lithic.tech/blog/2020-05/makefile-wildcards"&gt;last post&lt;/a&gt; how to use Makefile wildcards to write targets like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;migrate-to-%:
    @bundle exec rake migrate[$(*)] 
guard-%:
    @if [-z '${${*}}']; then echo 'ERROR: variable $* not set' &amp;amp;&amp;amp; exit 1; fi
logs: guard-STACK
    @awslogs get -w /ecs/$(STACK)_MyService

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



&lt;p&gt;So that we can build CLIs like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ make migrate-to-50
Migrating to version 50...

$ make logs
ERROR: variable STACK not set
$ STACK=qa make logs
...

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



&lt;p&gt;(Note the &lt;code&gt;@&lt;/code&gt; prefix on commands in the Makefile, it avoids the line being echoed to stdout)&lt;/p&gt;

&lt;p&gt;This is neat but it only works well for user-supplied values, like &lt;code&gt;"50"&lt;/code&gt;.There are cases where we want the user to supply an &lt;strong&gt;argument&lt;/strong&gt; , but not the &lt;strong&gt;value&lt;/strong&gt;.Say, for example, users want to specify ‘production’ to ‘staging’but we don’t want them to remember the URL to the server.&lt;/p&gt;

&lt;p&gt;We can use wildcards to dynamically select a Make variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;staging_url:=https://staging-api.lithic.tech
production_url:=https://api.lithic.tech

ping-%:
    curl "$($(*)_url)"

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



&lt;p&gt;And we can use it as so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ make ping-staging
curl "https://staging-api.lithic.tech"

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



&lt;p&gt;Okay, this example isn’t incredibly useful.But for some clients, we have multiple deployed versions of the same application,and we can use these variables to avoid having to remember where applications are deployed.&lt;/p&gt;

&lt;p&gt;For example, let’s say we have 3 versions of a codebase deployed in Heroku: one staging and two production apps.In the Make snippet below, each &lt;code&gt;_app&lt;/code&gt; variable refers to the name of a Heroku app.We can use that app name to get the database string using the Heroku CLI,and pass that to &lt;code&gt;psql&lt;/code&gt; (Postgres CLI).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;staging_app:=lithic-api-staging
production-pdx_app:=lithic-api-production
production-nyc_app:=lithic-api-production-nyc

psql-%:
    psql `heroku config:get DATABASE_URL --app=$($(*)_app)`

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



&lt;p&gt;Now to connect to staging, it’s as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ make psql-staging

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



&lt;p&gt;If we use Heroku’s Review Apps, we should also support an environment-variable version of these sorts of commands,since the app names are ephemeral. Instead of a wildcard, we’ll require the &lt;code&gt;APP&lt;/code&gt; environment variable is set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;psql-app: guard-APP
    psql `heroku config:get DATABASE_URL --app=${APP}`

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



&lt;h2&gt;
  
  
  Putting It All Together
&lt;/h2&gt;

&lt;p&gt;The example above has a couple small error cases that may confuse users:if &lt;code&gt;psql&lt;/code&gt; or &lt;code&gt;heroku&lt;/code&gt; are not on the &lt;code&gt;PATH&lt;/code&gt;,the command will error with a sort of cryptic error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ make psql-staging
psql `heroku config:get DATABASE_URL --app=lithic-api-staging`
/bin/sh: heroku: command not found
could not connect to server: No such file or directory

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



&lt;p&gt;Yuck! Can we use something like our lovely &lt;code&gt;guard-%&lt;/code&gt; target to declare our executable dependencies?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;You bet we can!&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cmd-exists-%:
    @hash $(*) &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 || \
        (echo "ERROR: '$(*)' must be installed and available on your PATH."; exit 1)

guard-%:
    @if [-z '${${*}}']; then echo 'ERROR: environment variable $* not set' &amp;amp;&amp;amp; exit 1; fi

psql-%: cmd-exists-heroku cmd-exists-psql
    psql `heroku config:get DATABASE_URL --app=$($(*)_app)`

psql-app: guard-APP cmd-exists-heroku cmd-exists-psql
    psql `heroku config:get DATABASE_URL --app=${APP}`
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now if you’re missing &lt;code&gt;heroku&lt;/code&gt; or &lt;code&gt;psql&lt;/code&gt;, you get a nice message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ make psql-staging
ERROR: 'heroku' must be installed and available on your PATH.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Who knew Make could be so &lt;em&gt;fun&lt;/em&gt; to use?&lt;/p&gt;

&lt;h2&gt;
  
  
  Not done with Make yet
&lt;/h2&gt;

&lt;p&gt;We’ll have one more blog post involving Make next week, along with a dump of a bunch of useful Makefile helpers.Stay tuned!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This was originally posted on my consultancy’s blog, at &lt;a href="https://lithic.tech/blog/2020-05/makefile-apps"&gt;https://lithic.tech/blog/2020-05/makefile-apps&lt;/a&gt;. If you have any questions, please leave a comment here!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>make</category>
      <category>programming</category>
      <category>cli</category>
    </item>
    <item>
      <title>Beautiful Makefiles with Wildcards</title>
      <dc:creator>Rob Galanakis</dc:creator>
      <pubDate>Fri, 22 May 2020 18:30:14 +0000</pubDate>
      <link>https://dev.to/lithictech/beautiful-makefiles-with-wildcards-32a</link>
      <guid>https://dev.to/lithictech/beautiful-makefiles-with-wildcards-32a</guid>
      <description>&lt;p&gt;Every single project we build includes a Makefile as a task runner. Every. Single. One.&lt;/p&gt;

&lt;p&gt;Why? Because it allows someone to jump into a codebase and start working with the same set of tools and commands as everyone else.&lt;/p&gt;

&lt;p&gt;Want to know how to install, build, test, deploy, and see what else you can do?Just open &lt;code&gt;Makefile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This may not be so important if you spend all your time on one monolith, but if you’re jumping around to many services or clients, it’s a lifesaver.&lt;/p&gt;

&lt;p&gt;It’s also &lt;em&gt;so, so nice&lt;/em&gt; for open source projects, I’m surprised GitHub doesn’t suggest it.&lt;/p&gt;

&lt;p&gt;In this post and future ones, we’ll go over some of the tricks we’ve learned building Makefiles in several dozen separate projects.&lt;/p&gt;

&lt;p&gt;Today’s lesson: &lt;strong&gt;Wildcards (%)&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic Arguments with Wildcards (%)
&lt;/h2&gt;

&lt;p&gt;Many popular languages include some (Make-inspired) script runner, so most commands look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;migrate:
    bundle exec rake migrate
install:
    yarn install
runserver:
    python ./manage.py runserver
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That’s nice, but what about when you want to supply arguments to one of those CLI commands.For example, how can you run &lt;code&gt;bundle exec rake migrate[50]&lt;/code&gt; to migrate to version 50, rather than latest?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Wildcards, that’s how!&lt;/em&gt;&lt;/strong&gt; For migrations, we can add a new command to migrate to a specific version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;migrate-to-%:
    bundle exec rake migrate[$(*)]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now if you want to migrate &lt;em&gt;to&lt;/em&gt; a specific version, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ make migrate-to-50
Migrating to version 50...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Well, we think that’s pretty cool, but what else can wildcards do?&lt;/p&gt;

&lt;h2&gt;
  
  
  Declarative Argument Dependencies
&lt;/h2&gt;

&lt;p&gt;The other way to configure Makefiles is with environment variables.Let’s say we use a consistent &lt;code&gt;STACK&lt;/code&gt; environment variable for working with deployed Cloudformation stacks (as we actually do).&lt;/p&gt;

&lt;p&gt;It can be pretty annoying to debug the errors if you forget to set STACK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;logs:
    awslogs get -w /ecs/$(STACK)_MyService
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That can be invoked (correctly) as &lt;code&gt;awslogs get -w /ecs/development_MyService&lt;/code&gt; or (incorrectly) as &lt;code&gt;awslogs get -w /ecs/_MyService&lt;/code&gt;. If it’s missing, your error will be about some unknown service or wrong file path, rather than about a missing parameter.&lt;/p&gt;

&lt;p&gt;Well, we have a special command we’ve been using for years that we’ll share with you now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;guard-%:
    if [-z '${${*}}']; then echo 'ERROR: variable $* not set' &amp;amp;&amp;amp; exit 1; fi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It’s maybe our favorite two lines of code in the world.&lt;/p&gt;

&lt;p&gt;Now, you can rewrite the &lt;code&gt;logs&lt;/code&gt; target like this, which is also more declarative and clearer about its dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;guard-%:
    if [-z '${${*}}']; then echo 'ERROR: variable $* not set' &amp;amp;&amp;amp; exit 1; fi
logs: guard-STACK
    awslogs get -w /ecs/$(STACK)_MyService
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, if you invoke &lt;code&gt;logs&lt;/code&gt; without &lt;code&gt;STACK&lt;/code&gt; set, you get a nice error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ make logs
ERROR: variable STACK not set
make: *** [guard-STACK] Error 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Wait, there’s more!
&lt;/h2&gt;

&lt;p&gt;There are a couple other wildcard-based tricks we still have in store, as well as some more Makefile goodness.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This was originally posted on my consultancy’s blog, at &lt;a href="https://lithic.tech/blog/2020-05/makefile-wildcards"&gt;https://lithic.tech/blog/2020-05/makefile-wildcards&lt;/a&gt;. If you have any questions, please leave a comment or &lt;a href="https://lithic.tech"&gt;get in touch&lt;/a&gt;!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>make</category>
      <category>makefiles</category>
      <category>softwaredevelopment</category>
      <category>ci</category>
    </item>
    <item>
      <title>Dynamic JavaScript and React Configuration</title>
      <dc:creator>Rob Galanakis</dc:creator>
      <pubDate>Mon, 18 May 2020 02:23:07 +0000</pubDate>
      <link>https://dev.to/lithictech/dynamic-javascript-and-react-configuration-2887</link>
      <guid>https://dev.to/lithictech/dynamic-javascript-and-react-configuration-2887</guid>
      <description>&lt;p&gt;Most of the frontends we build at Lithic are written in React.Normally we deploy them as static apps in &lt;a href="https://netlify.com"&gt;Netlify&lt;/a&gt;.This will write environment variables from &lt;code&gt;process.env&lt;/code&gt; directly into the compiled JavaScript.&lt;/p&gt;

&lt;p&gt;Sometimes, though, we need to dynamically configure the applications based on runtime,not build time, environment variables. The basic &lt;code&gt;create-react-app&lt;/code&gt; workflow doesn’t work in this situation.&lt;/p&gt;

&lt;p&gt;There are many approaches to runtime configuration of static JavaScript applications.Most of them involve writing out a &lt;code&gt;config.js&lt;/code&gt; file at server boot time,and having the client load this before or alongside the main JS bundle.In some solutions, the JS is dynamically templated.&lt;/p&gt;

&lt;p&gt;All of these approaches have downsides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loading &lt;code&gt;config.js&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; your main bundle introduces latency before you can load your app.&lt;/li&gt;
&lt;li&gt;Loading &lt;code&gt;config.js&lt;/code&gt; &lt;em&gt;alongside&lt;/em&gt; your main bundle means your app cannot synchronously access config,which introduces complexity.&lt;/li&gt;
&lt;li&gt;Templating your main bundle on each request is nontrivially complex(we love nginx too but the fewer script callouts the better).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is a solution, though: template config directly into &lt;code&gt;index.html&lt;/code&gt; at server/container boot time.&lt;/p&gt;

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

&lt;p&gt;We built &lt;strong&gt;&lt;a href="https://github.com/lithictech/runtime-js-env"&gt;runtime-js-env&lt;/a&gt;&lt;/strong&gt;to handle dynamic JS config with no downsides.It’s a simple Go program that rewrites &lt;code&gt;index.html&lt;/code&gt; to include a &lt;code&gt;window._jsenv&lt;/code&gt; object with your configpulled from &lt;code&gt;REACT_APP_&lt;/code&gt;, &lt;code&gt;NODE_&lt;/code&gt;, and &lt;code&gt;HEROKU_&lt;/code&gt; environment variables.&lt;/p&gt;

&lt;p&gt;You call it at container/server boot time,and the only change you need to make in your JS is change calls to &lt;code&gt;process.env&lt;/code&gt;into calls to &lt;code&gt;window._jsenv || process.env&lt;/code&gt;. See the GitHub repo for some examplesof how we handle this.&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;index.html&lt;/code&gt; file will be modified to include a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag inside your &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;.It’s safe to call multiple times, and uses Go’s HTML5 parser so should be valid for whatever you throw at it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;runtime-js-env&lt;/code&gt; is a Go program, so you’ll need Go installed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go get github.com/lithictech/runtime-js-env
$ runtime-js-env --help
NAME:
   runtime-js-env - A new cli application

USAGE:
   runtime-js-env [global options] command [command options] [arguments...]

COMMANDS:
   help, h Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --index value, -i value Path to the index.html file. Default to index.html in pwd. (default: "index.html")
   --window-var-name value, -w value Attribute name for the config object. (default: "_jsenv")
   --env-prefixes value, -p value Environment variable prefixes to copy into the config object. (default: "REACT_APP_", "NODE_", "HEROKU_")
   --indent value, -t value Indentation for each line in the config script tag. (default: " ")
   --help, -h show help (default: false)
$ runtime-js-env -i public/index.html

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



&lt;h2&gt;
  
  
  Feedback
&lt;/h2&gt;

&lt;p&gt;If you have any suggestions or feedback,please &lt;a href="https://github.com/lithictech/runtime-js-env"&gt;open an issue&lt;/a&gt;or &lt;a href="https://lithic.tech"&gt;get in touch directly&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This was originally posted on my consultancy’s blog, at &lt;a href="https://lithic.tech/blog/2020-05/react-dynamic-config"&gt;https://lithic.tech/blog/2020-05/react-dynamic-config&lt;/a&gt;. If you have any questions, please leave a comment or &lt;a href="https://lithic.tech"&gt;get in touch&lt;/a&gt;!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>configuration</category>
    </item>
    <item>
      <title>Should I use a graph database?</title>
      <dc:creator>Rob Galanakis</dc:creator>
      <pubDate>Wed, 13 May 2020 06:52:42 +0000</pubDate>
      <link>https://dev.to/lithictech/should-i-use-a-graph-database-eld</link>
      <guid>https://dev.to/lithictech/should-i-use-a-graph-database-eld</guid>
      <description>&lt;p&gt;One of our clients asked us the other day:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm setting up a web app that stores information about devices and the interconnected dependencies between devices. The app would have a web front for a user to navigate through the graph of devices and be able to click through each node, find related/linked nodes, and dive deeper into a given node.We're trying to decide what database to use, and thinking about a graph database. Do you have any advice?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Graph Databases (like Neo4j, AWS Neptune, and many others) are pretty amazing,but it's usually only a good idea to use one if you fit one of two criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You &lt;em&gt;really want&lt;/em&gt; to use a graph database. If you want to learn something new, go for it!But our job as consultant normally isn't to use unfamiliar technology.&lt;/li&gt;
&lt;li&gt;You have a "true graph problem."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It can sometimes be difficult to tell if you have a "true graph problem,"or just have a relational problem that &lt;em&gt;looks like&lt;/em&gt; a graph problem.&lt;/p&gt;

&lt;p&gt;"What devices are linked to other devices" just looks like a graph problem.It's pretty easily solved with just two tables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;devices(id, name, &amp;lt;other columns&amp;gt;)&lt;/code&gt; stores the device information (and would probably have foreign keys to/from other application tables)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;devices_network(upstream_id, downstream_id)&lt;/code&gt; is a join table specifying the relationships between devices (you may want some to add some constraints).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can then create a graph with some joins between those tables or multiple queries.This is going to be fast and efficient to get the network for any particular node,and maps really well to associations in Object Relational Mappers,wither eager loading/preloading.&lt;/p&gt;

&lt;p&gt;If you're not using an ORM, it's still pretty simple to build an in-memory network structureof some set of the graph to answer questions about deeper relationships.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a "true graph problem"?
&lt;/h3&gt;

&lt;p&gt;Graph problems are less about connections and nodes, and more about the edges between those nodes."What is connected to this node?" is an easy question to answer with a relational database, as we saw above.Some questions that are not easy to answer would be "what paths are available to travel between two nodes?"and "what are the costs/constraints between two nodes?"&lt;/p&gt;

&lt;p&gt;You can think of air travel. If we're traveling between airports,we're not so concerned with "what airports are connected to JFK," which is a relational problem.We're rather asking "what is the fastest/cheapest/shortest path between JFK and SFO or nearby airports,"which can only be solved in terms of a graph,because information about the edges/connections are fundamental to the solution.&lt;/p&gt;

&lt;p&gt;Put more abstractly: if the edges between your nodes have important properties,you probably have a graph problem. If the edges between nodes are just connections,you have a relational problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advice
&lt;/h3&gt;

&lt;p&gt;It's always much easier to run and develop against a relational database than a graph or any specialized database.Relational databases are a marvel of technology (especially PostgreSQL 😍),and you shouldn't throw that out lightly.Specialized tech means you’re going to have to do a lot of stuff from scratch, or with vastly more limited libraries.Far fewer tutorials and acquired knowledge. You’re just on your own for a whole lot more!&lt;/p&gt;

&lt;p&gt;That said, there are times graph and other specialized databases are the way to go.It's just a good idea to make sure you know why you're choosing it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This was originally posted on my consultancy's blog, at &lt;a href="https://lithic.tech/blog/2020-05/should-I-use-a-graph-database"&gt;https://lithic.tech/blog/2020-05/should-I-use-a-graph-database&lt;/a&gt;. If you have any questions, please leave a comment or &lt;a href="https://lithic.tech#contact"&gt;get in touch&lt;/a&gt;!&lt;/em&gt;&lt;/p&gt;

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