<?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: Caleb Collins-Parks</title>
    <description>The latest articles on DEV Community by Caleb Collins-Parks (@caleb15).</description>
    <link>https://dev.to/caleb15</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%2F216193%2F562a67ab-0cc5-4b69-abae-b995813e645c.jpeg</url>
      <title>DEV Community: Caleb Collins-Parks</title>
      <link>https://dev.to/caleb15</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/caleb15"/>
    <language>en</language>
    <item>
      <title>15Five's response to the Log4J RCE</title>
      <dc:creator>Caleb Collins-Parks</dc:creator>
      <pubDate>Sat, 29 Jan 2022 05:55:21 +0000</pubDate>
      <link>https://dev.to/15five/15fives-response-to-the-log4j-rce-cpo</link>
      <guid>https://dev.to/15five/15fives-response-to-the-log4j-rce-cpo</guid>
      <description>&lt;p&gt;When we learned about the &lt;a href="https://www.theguardian.com/technology/2021/dec/10/software-flaw-most-critical-vulnerability-log-4-shell"&gt;Log4j RCE&lt;/a&gt; in early December we quickly patched our servers, working on the weekend the day after the CVE was reported to get it done ASAP before hackers could strike. &lt;/p&gt;

&lt;p&gt;We started by escalating the incident to our security officer to get the appropriate attention on it. He immediately stopped the vulnerable server to prevent any exploits. This gave us time to do a thorough review of our services for use of Log4j. We used &lt;a href="https://www.techsolvency.com/story-so-far/cve-2021-44228-log4j-log4shell"&gt;https://www.techsolvency.com/story-so-far/cve-2021-44228-log4j-log4shell&lt;/a&gt; to see what services were affected. Fortunately, only the aforementioned server was affected.&lt;/p&gt;

&lt;p&gt;Updating the server was easy thanks to Docker. A quick increment to the tag version and a run of Ansible was all it took. Fortunately our other software was unaffected, so that was all the work needed. In less than a day the server was back online.&lt;/p&gt;

&lt;p&gt;To verify that Log4j no longer affected us we used &lt;a href="https://log4j-tester.trendmicro.com"&gt;https://log4j-tester.trendmicro.com&lt;/a&gt;, which reported a clean result. Problem solved! 🎉&lt;/p&gt;

&lt;p&gt;Lessons learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I learned about the Log4J vulnerability via Reddit. Therefore, browsing Reddit has a business purpose; learning about security vulnerabilities. That's totally what I'm doing on there. Any &lt;a href="https://imgur.com/XRBCL"&gt;adorable cat gifs&lt;/a&gt; on my screen is 100% related to security.&lt;/li&gt;
&lt;li&gt;You have more vendors and packages than you realize. When you see a vulnerability, think carefully about what it might affect.&lt;/li&gt;
&lt;li&gt;Containerization is good for security not just because it isolates attacks but also because the ease of updating makes attack response fast.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>security</category>
      <category>devops</category>
    </item>
    <item>
      <title>Migrating to Terraform: a retrospective</title>
      <dc:creator>Caleb Collins-Parks</dc:creator>
      <pubDate>Fri, 09 Apr 2021 16:17:39 +0000</pubDate>
      <link>https://dev.to/15five/migrating-to-terraform-a-retrospective-4cko</link>
      <guid>https://dev.to/15five/migrating-to-terraform-a-retrospective-4cko</guid>
      <description>&lt;h3&gt;
  
  
  Summary:
&lt;/h3&gt;

&lt;p&gt;At &lt;a href="http://15five.com/"&gt;15Five&lt;/a&gt; we migrated to Terraform in 8 months with a 3-person team. It went smoothly and gave us more confidence in our AWS infrastructure. When it came to setup a new VPC for a customer, the hours we invested returned to us in a speedy and simple setup, a process that would have been a massive pain if we had done it manually. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Stats:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Lines of code: ~16,000&lt;/li&gt;
&lt;li&gt;Number of commits: 903&lt;/li&gt;
&lt;li&gt;PR's: 514&lt;/li&gt;
&lt;li&gt;The team: Paul (principal engineer), James (devops manager), Caleb (SRE)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Timeline:
&lt;/h3&gt;

&lt;p&gt;2019.09 - I played around with Terraform for the first time in a company hackathon.&lt;br&gt;
2019.09 - I used Terraform to do my first AWS change.&lt;br&gt;
2019.11 - James joins team &amp;amp; starts work on terraform. Repo is split into a main terragrunt repo and a terraform repo for our various modules. At this point we only have two modules. CI is setup.&lt;br&gt;
2020.01 - we migrated our first environment&lt;br&gt;
2020.04.28 - preview environment migration attempt 1&lt;br&gt;
2020.04.29 - preview migration attempt 2 ✔️&lt;br&gt;
2020.05 - staging migration&lt;br&gt;
2020.06 - solitary customer VPC migration&lt;br&gt;
2020.06 - production migration&lt;/p&gt;

&lt;h3&gt;
  
  
  Takeaways:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Caleb:
&lt;/h4&gt;

&lt;p&gt;Pain points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Having two different repos is a bit awkward. I feel that having a monorepo or more CI would have been better, as the lack of CI feedback when changing code in the modules repo slowed things down. We'll probably be moving to a monorepo in the future.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What went well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hackathons are good for inspiring change.&lt;/li&gt;
&lt;li&gt;Checklists are great. It simply feels good to check things off, for one. It also makes you think of all the items to do ahead of time and makes sure that you don't forget anything. Hospitals have used checklists to massively lower infection rates, &lt;a href="https://www.nature.com/news/hospital-checklists-are-meant-to-save-lives-so-why-do-they-often-fail-1.18057"&gt;although the results depend on how effectively they are used&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;Terraform is great for developing a deep understanding of all the services involved in your infrastructure. By describing your infrastructure in code you develop a mental model of all the components involved, and have a written record of the tiny fiddly settings that might normally be hidden away behind some unintuitive UI icons.&lt;/li&gt;
&lt;li&gt;Migrating production went pretty smooth, that's worth its weight in gold.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  James:
&lt;/h4&gt;

&lt;p&gt;Pain Points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The monolith structure of Terraform modules results in very large artifacts - it would have preferable to break it down into multiple git repositories, one repo for each module.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What went well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have been able to upgrade Terraform without incident.&lt;/li&gt;
&lt;li&gt;We were able to develop 30-40% faster because of having a small agile team without overly restrictive bureaucracy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Paul:
&lt;/h4&gt;

&lt;p&gt;Pain points&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We should have pinned the Terraform version in version control to prevent accidental upgrade and to keep everyone on the same version (we ended up doing this later on with tfenv and a &lt;code&gt;.terraform-version&lt;/code&gt; file). &lt;/li&gt;
&lt;li&gt;None of the solutions for handling multiple environments seemed ideal, but James ended up solving this with Terragrunt once he came on board. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What went well?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It was a strong relief to have Terraform handle the setup of the environment. You just had to click a button, walk away, and the infrastructure would be ready by the time you came back. &lt;/li&gt;
&lt;li&gt;Using Terragrunt was a very clean way of configuring infrastructure across multiple environments. &lt;/li&gt;
&lt;li&gt;It checked off a lot of boxes for compliance and disaster recovery.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What could we have done better?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In retrospect I could have handed off more product work to other people to have more time to write Terraform and ensure best practices. &lt;/li&gt;
&lt;li&gt;We could have had nightly test runs - spinning up and tearing down infrastructure in another region to be confident it would always work. Metrics such as timing and money spent in setup would have been useful. The more metrics the better.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any other thoughts?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I wish I knew Terraform wrappers like &lt;a href="https://www.pulumi.com/why-pulumi/"&gt;Palumi&lt;/a&gt; were an option. However, it probably would have been overkill at the time.&lt;/li&gt;
&lt;li&gt;I have found that it saves more time to configure a cloud service with Terraform first and then checking UI. Doing it in the UI first and then translating that to Terraform is slower.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>aws</category>
    </item>
    <item>
      <title>Managing health checks at scale</title>
      <dc:creator>Caleb Collins-Parks</dc:creator>
      <pubDate>Fri, 05 Feb 2021 17:39:00 +0000</pubDate>
      <link>https://dev.to/15five/managing-health-checks-at-scale-4731</link>
      <guid>https://dev.to/15five/managing-health-checks-at-scale-4731</guid>
      <description>&lt;p&gt;At &lt;a href="https://www.15five.com" rel="noopener noreferrer"&gt;15Five&lt;/a&gt;, like many other companies, we use cron to schedule regularly occurring jobs. If a job fails to complete at the expected time or exits with the error code then we get an alert via &lt;a href="https://healthchecks.io" rel="noopener noreferrer"&gt;healthchecks.io&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;For a while this worked pretty well.&lt;/p&gt;

&lt;p&gt;But soon we faced a challenge. We wanted to expand health checks to all of our testing  environments, but that would require creating hundreds and hundreds of new checks. That's a lot of manual work, and why work when you can automate? &lt;/p&gt;

&lt;p&gt;I pondered different solutions like writing a script to &lt;a href="https://github.com/healthchecks/healthchecks/issues/266" rel="noopener noreferrer"&gt;copy the checks from one project to another&lt;/a&gt;, or a script to parse all the ping endpoints into a format that could easily be inserted into our codebase, or managing the health checks &lt;a href="https://github.com/kristofferahl/terraform-provider-healthchecksio" rel="noopener noreferrer"&gt;via terraform&lt;/a&gt;. But none of these solutions were perfect. I wanted something to completely automate the process.&lt;/p&gt;

&lt;p&gt;Fortunately, after talking with the Healthchecks  maintainer, it turns out they &lt;a href="https://github.com/healthchecks/healthchecks/issues/343#issuecomment-599259779" rel="noopener noreferrer"&gt;already had a basic script for that&lt;/a&gt;. Every time a job completed, it would do a simple call to the Healthcheck API, creating the check if it didn't already exist and returning the check endpoint. Ping the endpoint, and you're done! Easy peasy, no human work involved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-api-key-here

&lt;span class="c"&gt;# Check's parameters. This example uses system's hostname for check's name.&lt;/span&gt;
&lt;span class="nv"&gt;PAYLOAD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{"name": "'&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;hostname&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="s1"&gt;'", "timeout": 60, "grace": 60, "unique": ["name"]}'&lt;/span&gt;

&lt;span class="c"&gt;# Create the check if it does not exist.&lt;/span&gt;
&lt;span class="c"&gt;# Grab the ping_url from JSON response using the jq utility:&lt;/span&gt;
&lt;span class="nv"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://healthchecks.io/api/v1/checks/  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Api-Key: &lt;/span&gt;&lt;span class="nv"&gt;$API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PAYLOAD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  | jq &lt;span class="nt"&gt;-r&lt;/span&gt; .ping_url&lt;span class="sb"&gt;`&lt;/span&gt;

&lt;span class="c"&gt;# Finally, send a ping:&lt;/span&gt;
curl &lt;span class="nt"&gt;-m&lt;/span&gt; 10 &lt;span class="nt"&gt;--retry&lt;/span&gt; 5 &lt;span class="nv"&gt;$URL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I expanded on this to work with alert channels, measure start and end times, and to record failures.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Install &lt;a href="https://stedolan.github.io/jq/" rel="noopener noreferrer"&gt;jq&lt;/a&gt;, replace &lt;code&gt;healthchecks_api_key&lt;/code&gt; with your API key and ship the file with your cron jobs. Now you can pass the cron command to the script and it will do all your work for you. Creating a new environment? Just update the API key and you're good to go!&lt;/p&gt;

&lt;p&gt;We use Ansible to install jq and templatize the crontab and healthcheck file. Feel free to use Puppet instead, or manual distribution, or docker, or heck, redstone blocks in Minecraft, who am I to judge?&lt;/p&gt;

&lt;p&gt;This has been working well in our production environment for months now. As a bonus when we go into Healthchecks.io we can see a detailed history of job start and end times:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwfjoo4bohkxuqosqfulr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwfjoo4bohkxuqosqfulr.png" alt="Image of start and end pings with timing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's great to be able to set up a new datacenter and take comfort in a vibrant field of solid green checks, and the only thing I had to do to set it up was to update an API key!&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>devops</category>
      <category>sre</category>
      <category>showdev</category>
    </item>
    <item>
      <title>100,000 lines of Typescript: A data-backed retrospective</title>
      <dc:creator>Caleb Collins-Parks</dc:creator>
      <pubDate>Tue, 19 Jan 2021 17:16:18 +0000</pubDate>
      <link>https://dev.to/15five/100-000-lines-of-typescript-a-data-backed-retrospective-45dd</link>
      <guid>https://dev.to/15five/100-000-lines-of-typescript-a-data-backed-retrospective-45dd</guid>
      <description>&lt;h2&gt;
  
  
  PROLOGUE:
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;If you're more interested in the results of the migration than the journey itself, scroll on down to DATA &amp;amp; RESULTS&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;At first, types seemed tedious, and not worth the effort. I remember thinking, back in college, why was I specifying that a string (as indicated by the name &lt;code&gt;foo_str&lt;/code&gt;) was a string (as indicated by the quotation marks) was a string (as indicated by the type)? Then Typescript came with a revelation. Type inference&lt;sup id="fnref1"&gt;1&lt;/sup&gt;! The computer would do the grunt work for you, leaving you free to wander outside and sing and  dance and skip and shout joyfully into the sunlight&lt;sup id="fnref2"&gt;2&lt;/sup&gt;. I would never use Javascript again.&lt;/p&gt;

&lt;h2&gt;
  
  
  REGEXES EVERYWHERE
&lt;/h2&gt;

&lt;p&gt;I was using Javascript again.&lt;/p&gt;

&lt;p&gt;Or to be more accurate, my coworkers at my new company &lt;a href="https://15five.com"&gt;15Five&lt;/a&gt; were using Javascript. Those poor souls. I nobly volunteered (was assigned a ticket) to save them from their struggle (they were doing okay, really), by migrating the codebase to Typescript (by migrating the codebase to Typescript).&lt;/p&gt;

&lt;p&gt;This was my first time doing a migration of this size, and it was a daunting task. There were over 300 files and literally thousands upon thousands of Typescript errors. I knew migrating it by hand, alone, was out of the question, so I checked to see if there were any auto-migration tools. There was one! Yes! It failed to run! Yes! Wait, No!&lt;/p&gt;

&lt;p&gt;Unfortunately, that was the only one I found. Other large migrations I read of were done by &lt;a href="https://www.lucidchart.com/techblog/2017/11/16/converting-600k-lines-to-typescript-in-72-hours/"&gt;teams of people with a solid chunk of time &lt;/a&gt; dedicated solely to the migration, and the assistance of specialized tools.&lt;/p&gt;

&lt;p&gt;Fortunately, we already used React &lt;a href="https://reactjs.org/docs/typechecking-with-proptypes.html"&gt;PropTypes&lt;/a&gt;, which are somewhat similar to Typescript types. In some cases, very similar. A simple search/replace across the entire project (VSCode made this very easy) sufficed to take care of basic cases like converting &lt;code&gt;PropTypes.string&lt;/code&gt; to &lt;code&gt;string&lt;/code&gt;. This alone was a massive time saver as I could change ~300 files at once. &lt;/p&gt;

&lt;p&gt;But plain text replacement can still be slow, as you have to go through each scenario one by one. With regex you can handle multiple scenarios at once:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PropTypes.(string|number|object|symbol|any).isRequired&lt;/code&gt;&lt;br&gt;
Substitute with &lt;code&gt;$1&lt;/code&gt; to replace all the primitive PropTypes at once!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PropTypes.arrayOf\((\w+)\).isRequired&lt;/code&gt;&lt;br&gt;
Substitute with &lt;code&gt;$1[]&lt;/code&gt; to replace one-line array types.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;([^:]+): PropTypes.array,&lt;/code&gt;&lt;br&gt;
Substitute with &lt;code&gt;$1?: any[];&lt;/code&gt; to replace bare arrays.&lt;/p&gt;

&lt;p&gt;Regexes aren't as powerful as &lt;a href="https://github.com/facebook/jscodeshift"&gt;codemods&lt;/a&gt;, but they were enough for me. Within a week I had a PR merged that converted the entire react codebase to Typescript.&lt;/p&gt;
&lt;h2&gt;
  
  
  TSC-SILENT
&lt;/h2&gt;

&lt;p&gt;But I wasn't done. Not by a long shot. Although the PropTypes were in Typescript, and the files were technically Typescript files with a .ts extension, there were still thousands of miscellaneous type errors that polluted a Typescript run. Devs could still have the benefits of Typescript on new code, but on old code it wasn't as powerful. Furthermore, the type errors prevented us from running Typescript in our continuous integration (CI) environment.&lt;/p&gt;

&lt;p&gt;Fortunately, I found a tool called tsc-silent, that allowed you to run Typescript while silencing certain types of errors. That way the CI could catch any new errors that appeared, while also giving us a progress report on how many old errors were left. Tsc-silent was highly configurable, letting us silence certain errors in directors of the old codebase while catching all errors in other directories.&lt;/p&gt;

&lt;p&gt;Another option I could have done but didn't think of at the time was a snapshot test. By saving Typescript errors to a file and failing CI if the run doesn't match the file, you can catch any new errors introduced and keep track of existing errors. For more details see &lt;a href="https://dylanvann.com/incrementally-migrating-to-typescript"&gt;https://dylanvann.com/incrementally-migrating-to-typescript&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  THE LONG GRIND
&lt;/h2&gt;

&lt;p&gt;For a while I tried tackling the remaining Typescript errors by myself. This went slowly, given my limited time and lack of expertise in the codebase. Eventually, I realized I needed subject matter experts, so I created an every-other-week meeting with a few generous volunteers from the frontend team. Thanks to the expertise of the volunteers, we made good headway at first, but as the months went by each type error took longer and longer to solve. We were so close - only 500 errors left! Yet fixing just a couple errors could take an entire hour. &lt;/p&gt;

&lt;p&gt;For example, certain errors may involve your code's use of a foreign package, so in order to fix it you need a good knowledge of both your code and the package's API. If the library doesn't have good types then the issue can take a while to untangle. The fix may pretty easy (one PR literally just added &lt;code&gt;&amp;lt;Date&amp;gt;&lt;/code&gt;) but &lt;em&gt;knowing&lt;/em&gt; how to fix it is a whole other story.&lt;/p&gt;

&lt;p&gt;As 2020 neared its end (good riddance) I decided to switch strategies.&lt;/p&gt;
&lt;h2&gt;
  
  
  TS-MIGRATE
&lt;/h2&gt;

&lt;p&gt;Airbnb open-sourced their automatic JS-&amp;gt;TS migration tool, a project aptly called &lt;a href="https://github.com/airbnb/ts-migrate"&gt;ts-migrate&lt;/a&gt;. Although our codebase was already migrated, the feature to automatically add ts-expect-error comments to all existing errors seemed useful. Using that to ignore existing errors would let us Typescript directly in our CI instead of tsc-silent and prevent new errors from creeping in. Running it took a while, but soon tsc produced a clean run! I added it to our CI, and a simple grep allowed us to keep track of the remaining type errors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Leftover type errors per file&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grep -cR "// @ts-expect-error ts-migrate" your/path/here | grep -v :0&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Number of leftover type errors&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grep -R "// @ts-expect-error ts-migrate" your/path/here | wc -l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's now ~200 errors left, but a lot of them will be gone once we refactor out our usage of Redux. I would like to say we got down to 0 errors, as that would make for a neat and tidy ending to this story, but the real world is not so perfect. When Redux is gone we can go through the remaining errors and decide what is worth fixing.&lt;/p&gt;

&lt;h2&gt;
  
  
  DATA &amp;amp; RESULTS:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Team size&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;11 Frontend engineers in total (not directly involved with TS)&lt;/li&gt;
&lt;li&gt;3-4 engineers directly involved in migration&lt;/li&gt;
&lt;li&gt;1 Project lead (not included in above)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For context, most of our employees are senior or mid-level coders. We have no interns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codebase Size&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jun 19th, 2019: 291 files, 25,866 lines&lt;/li&gt;
&lt;li&gt;Dec 7th, 2020: 1560 files, 126,816 lines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;PR's&lt;/strong&gt;: 47&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Person-hours&lt;/strong&gt;:&lt;br&gt;
&lt;em&gt;very rough estimates follow&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assuming each PR ~= 1 hour, that's 47 hours&lt;/li&gt;
&lt;li&gt;Plus 10 hours for meetings&lt;/li&gt;
&lt;li&gt;Plus 5 hours for PR reviews&lt;/li&gt;
&lt;li&gt;Total: 62 hours&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we had ts-migrate at the start, that might have saved 9 hours or so.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Number of TS Errors Fixed&lt;/strong&gt;: 3,168&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jun 19th, 2019: Started work&lt;/li&gt;
&lt;li&gt;Jun 25th, 2019 (6 days): Migrated to TS&lt;/li&gt;
&lt;li&gt;Sep 30th, 2019 (3 months): TS enforced in CI&lt;/li&gt;
&lt;li&gt;Dec 7th, 2020 (1.5 years): Vast majority of errors fixed, TS used directly in CI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that most of the benefit of the migration was realized within the first few months. This follows the Pareto Principle - 80% of the outcome results from 20% of the work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bugs&lt;/strong&gt;: 0 bugs, thanks to great reviews by &lt;a href="https://github.com/razh"&gt;Razh&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Survey data&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.google.com/forms/d/1H0XjPCu5mF2TVllrjHo7HExyUT4Ajl8pqjWBNsfuX3s/viewanalytics"&gt;Mid-way Survey&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.google.com/forms/d/e/1FAIpQLSdhYXYOXfQOfqg7-YXPWang3BMrnSlU96GYccb5ba7eXmZ6Zg/viewanalytics"&gt;Final Survey&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although the sample size was too small to be statistically valid, the survey results were very good. Most developers were happy with Typescript. It caught bugs, improved intellisense, and made refactoring easier. The survey did reveal mixed results on making development faster, but that is no surprise. The work it takes to add types somewhat negates the improved development speed from refactoring and intellisense. The benefit you are left with is catching bugs.&lt;/p&gt;

&lt;h2&gt;
  
  
  SUMMARY:
&lt;/h2&gt;

&lt;p&gt;Converting to Typescript with ts-migrate is a quick and easy win to improve your frontend code. Fixing all Typescript errors on a large codebase, on the other hand, is not easy nor quick. Going through them all can be a slog, so you should maintain inertia by holding type-fixing meetings or hackathons. Certain type errors may be rather difficult to resolve, so you should decide ahead of time the maximum amount of effort you are willing to spend. You can realize the majority of benefit from Typescript without fixing all the errors, so you don't need to worry about fixing everything in one long all-nighter. You can take your time - so why not start today?&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;I don't mean to suggest Typescript was the first to come about with type inference, just that it was the first to bring it to Javascript at a large scale. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Or to stay inside and write articles about how free you are ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>typescript</category>
      <category>computerscience</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Announcing Rocket Releaser</title>
      <dc:creator>Caleb Collins-Parks</dc:creator>
      <pubDate>Tue, 15 Dec 2020 17:15:38 +0000</pubDate>
      <link>https://dev.to/15five/announcing-rocket-releaser-4phe</link>
      <guid>https://dev.to/15five/announcing-rocket-releaser-4phe</guid>
      <description>&lt;p&gt;&lt;a href="https://www.15five.com"&gt;15Five&lt;/a&gt; has open-sourced a python package for generating release notes and sending them to Slack! Take a look below:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/15five"&gt;
        15five
      &lt;/a&gt; / &lt;a href="https://github.com/15five/rocket_releaser"&gt;
        rocket_releaser
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Python library for release notes / labeling upon deploys
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Rocket Releaser &lt;a href="https://circleci.com/gh/15five/rocket_releaser" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/63248f26e20a3e468fe339d38bd0e5008498129a7f5c4486512295e3ae86325b/68747470733a2f2f636972636c6563692e636f6d2f67682f3135666976652f726f636b65745f72656c65617365722e7376673f7374796c653d73766726636972636c652d746f6b656e3d30323261336138393731386430383861633861373337623264303332383063346331383634656430" alt="CircleCI"&gt;&lt;/a&gt; &lt;a href="https://badge.fury.io/py/rocket-releaser" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/006b446d95500f501025a68fce5fed69c65c3d17d98f23f89e7687a70d57cd4e/68747470733a2f2f62616467652e667572792e696f2f70792f726f636b65742d72656c65617365722e737667" alt="PyPI version"&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Library for creating release notes based on PR descriptions for a set of git changes.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/35c5d1bf8eca2659fe1aab0d626834aee8870785df742de861a01bce558a9bb2/687474703a2f2f692e696d6775722e636f6d2f356830717a61492e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/35c5d1bf8eca2659fe1aab0d626834aee8870785df742de861a01bce558a9bb2/687474703a2f2f692e696d6775722e636f6d2f356830717a61492e706e67" alt="example slack message"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Installation:&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;pip install rocket-releaser&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
Usage:&lt;/h2&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;python -m rocket_releaser github_token start_sha end_sha github_org github_repo -r repo_location --vpc_name staging --env_name staging --search_branch staging --slack_webhook_key slack_key&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This would label PR's inbetween first and second sha with "staging" and send the release notes to slack
If you are using a personal github account the "github_org" would be your github username.&lt;/p&gt;
&lt;p&gt;The github token must have "repo" scope access and the token's user must have write access to the repo.&lt;/p&gt;
&lt;p&gt;You can also pass in Jira paramaters to label Jira tickets.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--jira_token jiraToken --jira_username bob@company.com --jira_url https://company.atlassian.net&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
PR format:&lt;/h2&gt;
&lt;p&gt;To label PR's and tickets your PR's should be formatted like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- Detailed PR description for reviewers goes here... --&amp;amp;gt
RELEASES
Change default avatar image #public Closes [ENG-1234]
&amp;lt;!--
- Newline after RELEASES (need this for proper formatting&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/15five/rocket_releaser"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This allows our QA and other teams to easily see what changes have been deployed and what needs testing. The package also labels PR's and tickets, so everyone is kept in the loop as to what stage of the deployment process their code is in.&lt;/p&gt;

&lt;p&gt;The repository is based off of the open-source &lt;a href="https://dev.to/15five/ci-cd-python-packaging-through-circleci-30f2"&gt;circleci boilerplate&lt;/a&gt; announced earlier.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>python</category>
      <category>devops</category>
    </item>
    <item>
      <title>CI/CD python packaging through CircleCI</title>
      <dc:creator>Caleb Collins-Parks</dc:creator>
      <pubDate>Mon, 16 Nov 2020 17:36:10 +0000</pubDate>
      <link>https://dev.to/15five/ci-cd-python-packaging-through-circleci-30f2</link>
      <guid>https://dev.to/15five/ci-cd-python-packaging-through-circleci-30f2</guid>
      <description>&lt;p&gt;&lt;a href="https://www.15five.com" rel="noopener noreferrer"&gt;15Five&lt;/a&gt; has open-sourced a boilerplate template for a python package with continuous integration and delivery through &lt;a href="https://circleci.com/" rel="noopener noreferrer"&gt;CircleCI&lt;/a&gt;. Take a look below!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/15five" rel="noopener noreferrer"&gt;
        15five
      &lt;/a&gt; / &lt;a href="https://github.com/15five/python-circleci-package-boilerplate" rel="noopener noreferrer"&gt;
        python-circleci-package-boilerplate
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      boilerplate for a python package with CI/CD through circleci
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FULL CI/CD through Circleci with the works (black linting, pip caching, tests against multiple python versions, test summary, coverage results, automatic package deploy each push to master)&lt;/li&gt;
&lt;li&gt;Package directory structure already laid out&lt;/li&gt;
&lt;li&gt;Makefile and other sensible files and configuration already present&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're using Travis I suggest using the popular python package &lt;a href="https://github.com/audreyr/cookiecutter-pypackage" rel="noopener noreferrer"&gt;cookie cutter template&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>circleci</category>
      <category>devops</category>
      <category>python</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Using DjangoQL for a better django admin search</title>
      <dc:creator>Caleb Collins-Parks</dc:creator>
      <pubDate>Mon, 05 Oct 2020 18:45:00 +0000</pubDate>
      <link>https://dev.to/15five/using-djangoql-for-a-better-django-admin-search-2dj</link>
      <guid>https://dev.to/15five/using-djangoql-for-a-better-django-admin-search-2dj</guid>
      <description>&lt;p&gt;A reasonable Django admin search looks like this:&lt;/p&gt;

&lt;p&gt;Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MusicianAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelAdmin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;search_fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;first_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;last_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;User search input:&lt;br&gt;
&lt;code&gt;john lennon&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Resulting SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not too bad, right?&lt;/p&gt;

&lt;p&gt;But now imagine your &lt;a href="https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields" rel="noopener noreferrer"&gt;search fields&lt;/a&gt; look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReviewerReporterAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelAdmin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;search_fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reporter__first_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reporter__last_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reporter__email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reporter__company__name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reporter__company__subdomain&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reviewer__first_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reviewer__last_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reviewer__email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting SQL will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reporter__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__email&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__subdomain&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__email&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reporter__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__email&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__subdomain&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__email&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yikes. But computers are powerful. That's still manageable.&lt;/p&gt;

&lt;p&gt;Now try this one on for size:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reporter__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__email&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__subdomain&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__email&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reporter__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__email&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__subdomain&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__email&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reporter__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%is%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%is%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__email&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%is%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%is%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__subdomain&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%is%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%is%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%is%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__email&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%is%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reporter__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%a%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%a%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__email&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%a%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%a%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__subdomain&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%a%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%a%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%a%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__email&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%a%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reporter__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%great%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%great%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__email&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%great%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%great%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__subdomain&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%great%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%great%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%great%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__email&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%great%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reporter__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%singer%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%singer%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__email&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%singer%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%singer%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__subdomain&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%singer%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%singer%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%singer%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__email&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%singer%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reporter__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%and%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%and%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__email&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%and%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%and%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__subdomain&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%and%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%and%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%and%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__email&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%and%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reporter__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%songwriter%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%songwriter%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__email&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%songwriter%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%songwriter%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reporter__company__subdomain&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%songwriter%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__first_name&lt;/span&gt;  &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%songwriter%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%songwriter%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;reviewer__email&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%songwriter%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's what happens when the user searches for "john lennon is a great singer and songwriter". Each word is searched against every field, leading to the giant SQL block above! Here's a real-world example of what this looks like:&lt;/p&gt;

&lt;p&gt;(table and field names obfuscated):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
&lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"create_ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"sasquatch_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"yolo_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"to_scale"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"extra"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"spiders"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_epic_win"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_superorange"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"passport"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"number_swords"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"scim_orangename"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"orangename"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"mango"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"canonical_mango"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"yolo_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"global_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"first_kiss"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_kiss"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"knightlyTitle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"IVotedDidYou"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"IVotedDidYou_length"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"aspirational_knightlyTitle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"aspirational_knightlyTitle_length"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"aspirational_IVotedDidYou"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"aspirational_IVotedDidYou_length"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"vulnerabilities"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"vulnerabilities_length"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"banana_mansion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"banana_mega_mansion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"IEnjoyThinkingOfRandomNames"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"ButImNotSureAnyoneWillActuallyReadThem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"MakingUpRandomNamesIsItsOwnReward"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_yolo_admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_pineapple_admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"can_view_all_oranges"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"require_spiders_change"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_vip"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_vip_bossperson"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_a_bro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_not_a_bro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"saml_orange_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"first_mango_eaten"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_spiders_change_ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"create_ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"update_ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"num_dirty_mangoes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"howdouspellmangos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_seen_ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"ithinkitswithae"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"ahhhhh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"imrunningoutofrandomnames"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"howmanymorefields"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"arethere"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"uggghhh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_ides_of_march"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"biweekly_is_ides_of_march"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"biweekly_is_ides_of_march_which_week"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"monthly_is_ides_of_march"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"monthly_is_ides_of_march_which_in_month"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"prefs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"toilet_paper"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"skip_yolo_wide_questions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"blorp_type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"bloop_type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"number_angry_zebras"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"can_manage_oranges"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"sick_hair_yo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"IEnjoyThinkingOfRandomNames"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"prefs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"apocalypse_start_date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"apocalypse_length_days"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"mango_domain"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"hypeperson_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"toilet_paper"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"create_ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"update_ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"arethere"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"num_dirty_mangoes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"converted_to_paying_ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"stopped_paying_ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_ides_of_march"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"biweekly_is_ides_of_march"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"biweekly_is_ides_of_march_which_week"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"monthly_is_ides_of_march"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"monthly_is_ides_of_march_which_in_month"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"uggghhh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_vip_bossperson"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_a_bro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"smart_banana_access"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"happiness_access"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"smart_potato_access"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"attachments_access"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"smart_potato_access"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_sad_banana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_angry_banana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_secret_banana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_nice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"is_delicious"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"carrot_hypeman"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"potato_hypeman"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"number_of_people_with_eyebrows"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"banana_owner_id"&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"banana_table"&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;OUTER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"sasquatch_id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;OUTER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"yolo_id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%this%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"first_kiss"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%this%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_kiss"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%this%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"mango"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%this%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%this%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"sick_hair_yo"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%this%'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%is%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"first_kiss"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%is%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_kiss"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%is%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"mango"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%is%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%is%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"sick_hair_yo"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%is%'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%a%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"first_kiss"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%a%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_kiss"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%a%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"mango"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%a%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%a%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"sick_hair_yo"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%a%'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%test%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"first_kiss"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%test%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_kiss"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%test%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"mango"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%test%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%test%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"sick_hair_yo"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%test%'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%query%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"first_kiss"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%query%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_kiss"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%query%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_orange"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"mango"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%query%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%query%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"ff_yolo"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"sick_hair_yo"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%query%'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="nv"&gt;"banana_table"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your eyes glazed over that example, don't worry. The exact syntax doesn't matter - the point is that such a large query is not a theoretical example, it can actually happen!&lt;/p&gt;

&lt;p&gt;Still, when running against a local database the query only took roughly 4 milliseconds. Fast, but the table in my local database only has 70 rows. Slow code will remain silent at that scale, lurking in the background and waiting to pounce. And it likes to rear its head at the worst possible moment - production.&lt;/p&gt;

&lt;p&gt;In production we have over 3 MILLION rows. Divide 3,847,951 by 70 to get the ratio of how much larger production is. Multiply the time it took with 70 rows (4ms) by the ratio and we can predict that the same search in production would take 219,882 milliseconds, or 219 seconds*! Ain't nobody got time for that. Seriously, our pages time out after 30 seconds, so there's literally not enough time for that.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You could simply use less search fields. But what if the user wants to search against a field you removed? You're reducing functionality to improve performance, which may or may not be an acceptable tradeoff. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You could buy a better database. But you might not have the funds for that yet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You could add indexes to your tables. But this requires careful consideration for each table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You could add a dedicated mirror database for django admin. But you might not have the funds for that yet. (This was one of the improvements we made)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You could &lt;a href="https://www.youtube.com/watch?v=JjjpAYEnK7k" rel="noopener noreferrer"&gt;switch to Elasticsearch&lt;/a&gt;. But that will take time to implement, add complexity, and again, take funds to host.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If only the user could easily choose what fields they want to search against, that would help relieve the problem. Luckily, there's a library that does exactly that; enter &lt;a href="https://github.com/ivelum/djangoql" rel="noopener noreferrer"&gt;DjangoQL&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fivelum%2Fdjangoql%2Fmaster%2Fdjangoql%2Fstatic%2Fdjangoql%2Fimg%2Fcompletion_example_scaled.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fivelum%2Fdjangoql%2Fmaster%2Fdjangoql%2Fstatic%2Fdjangoql%2Fimg%2Fcompletion_example_scaled.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By letting users choose what fields to search against you can massively speed up searches. Remember that SQL query I showed earlier?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the user selects a specific field the query becomes simpler, and thus faster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%john%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="s1"&gt;'%lennon%'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have a lot of search fields and data, this can result in a large performance improvement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Page      |  # Items   |  Performance
--------------------------------------------------------------------------
XXXX      |  ~1,000    |  no performance difference
YYYY      |  ~100,000  |  up to ~5x increase in search speed
ZZZZ      | ~1,000,000 |  searching can take so long it times out unless DjangoQL is used
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is also dependent upon network speed, hardware speed, database indexes, and a whole host of other factors. But generally speaking if you have over 100k rows and a bunch of search fields you'll probably see a performance increase.&lt;/p&gt;

&lt;p&gt;The neat thing is that the performance improvement is really just a side-benefit of the library. The main benefit is giving your users a query language that is much more powerful and flexible than just being able to do text matches.&lt;/p&gt;

&lt;p&gt;The final benefit is that DjangoQL is a very straightforward addition to your code. You just make a simple class that inherits from &lt;code&gt;DjangoQLSearchMixin&lt;/code&gt; and &lt;code&gt;admin.ModelAdmin&lt;/code&gt; and use that instead of &lt;code&gt;admin.ModelAdmin&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FLG8R79y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FLG8R79y.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repeat changes in the bottom file for the rest of your files, and that's basically it!&lt;/p&gt;

&lt;p&gt;This isn't going to solve your performance problems, but it should help a bit assuming you educate your users on how to use it. It's a easy yet powerful band-aid you can apply while you work on more long-term fixes. Even if you don't care about speeding up your code it's still useful, so it's a win-win!&lt;/p&gt;

</description>
      <category>django</category>
      <category>djangoql</category>
      <category>performance</category>
      <category>python</category>
    </item>
    <item>
      <title>How to (temporarily!) ignore errors during a TypeScript migration</title>
      <dc:creator>Caleb Collins-Parks</dc:creator>
      <pubDate>Fri, 14 Aug 2020 15:56:05 +0000</pubDate>
      <link>https://dev.to/15five/how-to-temporarily-ignore-errors-during-a-typescript-migration-doe</link>
      <guid>https://dev.to/15five/how-to-temporarily-ignore-errors-during-a-typescript-migration-doe</guid>
      <description>&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; You might want to skip this approach and use &lt;a href="https://dev.to/kojikanao/introduce-typescript-to-react-js-project-with-ts-migrate-190h"&gt;ts-migrate&lt;/a&gt; instead. It can automatically migrate your JS to TS and add @ts-expect-error comments to type errors you need to resolve by hand.&lt;/p&gt;




&lt;p&gt;Last year at &lt;a href="https://15five.com" rel="noopener noreferrer"&gt;15Five&lt;/a&gt; we started migrating our frontend react codebase to TypeScript. I went wild with regexes and Vscode's search/replace all feature, adding types and changing syntax in mass. But regex can only get you so far. There was still thousands of type errors, with each type needing to be reviewed manually. Some were easy to fix, others were much harder. This was going to take a lot of time. Time that I didn't have - my responsibility was DevOps after all, and I was migrating code to TypeScript in my free time. Frontend engineers also worked on the migration but they needed time to ship features.&lt;/p&gt;

&lt;p&gt;I could've abandoned the migration and came back to it later. But without validation in our CI, untyped code would sneak in and leave a even bigger problem in the future. Luckily I came across &lt;a href="https://github.com/evolution-gaming/tsc-silent" rel="noopener noreferrer"&gt;tsc-silent&lt;/a&gt;! &lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/evolution-gaming" rel="noopener noreferrer"&gt;
        evolution-gaming
      &lt;/a&gt; / &lt;a href="https://github.com/evolution-gaming/tsc-silent" rel="noopener noreferrer"&gt;
        tsc-silent
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      `tsc` with `--suppress` flag
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;&lt;code&gt;tsc-silent&lt;/code&gt;&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;The purpose of the wrapper is to execute TypeScript compiler but suppress some error messages
coming from certain files/folders. For example, this can be used to enable &lt;code&gt;noImplicitAny&lt;/code&gt; in
some parts of the project while keeping it disabled in others.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installing&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install -g tsc-silent&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;tsc-silent --project &amp;lt;path&amp;gt; [--suppress config | --suppressConfig path] [--compiler path] [--watch]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Synopsis&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;--project, -p    Path to tsconfig.json

--compiler       Path to typescript.js.
                 By default, uses `./node_modules/typescript/lib/typescript.js`.

--suppress       Suppressed erros.
                 E.g. `--suppress 7017@src/js/ 2322,2339,2344@/src/legacy/`.

--suppressConfig Path to supressed errors config.
                 See documentation for examples.

--watch, -w      Run in watch mode.

--stats          Print number of suppressed errors per path and error code.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Suppress config&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;You have to pass either &lt;code&gt;--suppress&lt;/code&gt; or &lt;code&gt;--suppressConfig&lt;/code&gt;.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;&lt;code&gt;--suppress&lt;/code&gt;&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;Let's ignore error &lt;code&gt;7017&lt;/code&gt; in &lt;code&gt;src/js/&lt;/code&gt; directory and errors &lt;code&gt;2322, 2339, 2344&lt;/code&gt; in &lt;code&gt;/src/legacy/&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;tsc-silent -p tsconfig.json --suppress 7017@/src/js/ 2322,2339,2344@/src/legacy/&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;or, ignore all errors in &lt;code&gt;/src/legacy/&lt;/code&gt; folder&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;tsc-silent -p tsconfig.json --suppress&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/evolution-gaming/tsc-silent" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Tsc-silent lets you ignore certain TypeScript errors. By ignoring the errors that came from code not yet migrated, I could add TypeScript to our CI without error! For the errors that were fixed, tsc-silent would raise an error if they came back again.&lt;/p&gt;

&lt;p&gt;This was quite easy to configure:&lt;/p&gt;

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

yarn tsc-silent &lt;span class="nt"&gt;--project&lt;/span&gt; tsconfig.json &lt;span class="nt"&gt;--suppress&lt;/span&gt; 2339,7006,2345,2739,2532,2307,7031,2741,2554,7053,7005,2740,2538,2531,2551,2571,2533,2305,2322,7015,2305,2722,7034,2724,2349,7016,1208,2749,2604,2363,2362,2605,2555,2464,2525,2559,2362@ff/static/modules 2305@node_modules &lt;span class="nt"&gt;--stats&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;At this point you might be thinking "Darn, that's a lot of errors you're ignoring! Isn't that bad practice? Is it even worth it if so many errors are ignored"?&lt;/p&gt;

&lt;p&gt;A valid concern, but even catching just a few errors is better than catching no errors at all. And this is the dumb approach - our resident code ninja (or "Frontend-related human being" as he humbly calls himself) &lt;a href="https://github.com/razh" rel="noopener noreferrer"&gt;Razh&lt;/a&gt; came up with a much smarter solution.&lt;/p&gt;

&lt;p&gt;By passing in a configuration file to tsc-silent, we can choose what errors are ignored on which paths!&lt;/p&gt;

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

yarn tsc-silent &lt;span class="nt"&gt;--project&lt;/span&gt; tsconfig.json &lt;span class="nt"&gt;--suppressConfig&lt;/span&gt; tsc-silent.config.js &lt;span class="nt"&gt;--stats&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;tsc-silent.config.js&lt;/p&gt;

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

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;suppress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;pathRegExp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/ff/static/modules/components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;codes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2322&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2339&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2345&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2362&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2363&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2532&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2555&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2739&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2769&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7016&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;pathRegExp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/ff/static/modules/realtime_feedback&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;codes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2322&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2345&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2769&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;other&lt;/span&gt; &lt;span class="nx"&gt;suppressions&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;shown&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now for new folders we have &lt;em&gt;full&lt;/em&gt; TypeScript error checking! For old folders we can be more selective about what errors we ignore too. As a bonus the tsc-silent output gives you information on exactly how many errors are left that you need to fix if you use the &lt;code&gt;--stats&lt;/code&gt; option. In the example below you can see that there are a couple errors with only 1 instance left - those would be easy targets to fix and start validating against.&lt;/p&gt;

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

  {
    "codes": {
      "2322": 4,
      "2339": 2,
      "2345": 3,
      "2362": 2,
      "2363": 2,
      "2555": 1,
      "2739": 2,
      "2769": 11,
      "7016": 1
    },
    "pathRegExp": "/\\/ff\\/static\\/modules\\/components/",
    "total": 28
  },


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

&lt;/div&gt;

&lt;p&gt;In conclusion, if you're migrating a large project to typescript tsc-silent can be quite useful. It lets you validate errors in CI even when your migration is not finished yet. Just don't use it as a excuse to ignore errors forever - there's a reason TypeScript raises an error, and even if it's not a bug it's still good to fix to increase the quality of your code. Someday we will finish up our migration and our need for tsc-silent will be gone. Until then, it's served us well.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to never forget you're in production</title>
      <dc:creator>Caleb Collins-Parks</dc:creator>
      <pubDate>Tue, 11 Aug 2020 02:57:14 +0000</pubDate>
      <link>https://dev.to/15five/how-to-never-forget-you-re-in-production-2gcj</link>
      <guid>https://dev.to/15five/how-to-never-forget-you-re-in-production-2gcj</guid>
      <description>&lt;h2&gt;
  
  
  The Scenario
&lt;/h2&gt;

&lt;p&gt;You now have production access!&lt;br&gt;
You shell into the server and .... huh&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Welcome to Ubuntu 50.01.1

  System information as of Sun Aug  9 20:29:10 UTC 2050

  System load:  0.2                Processes:           149
  Usage of /:   42.4% of 16 bits   Users logged in:     0
  Memory usage: 67%                IP address for ens5: 8.8.8.8
  Swap usage:   0%

 * Are you ready for Kubernetes 5.19? It's nearly here! Try RC3 with
   sudo snap install microk8s --channel=1.19/candidate --classic

   https://microk8s.io/ has docs and details.

 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch

0 packages can be updated.
0 updates are security updates.


Last login: Sun Aug  9 20:22:21 2050 from 192.16.184.0
bob@dns0:~$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;It looks exactly the same as any server†. Pretty boring, really. Months go by, and shelling into production becomes old hat to you. One day you're tasked with deleting everything in a test server. A quick &lt;code&gt;rm -rf *&lt;/code&gt;, and bam, it's done.&lt;/p&gt;

&lt;p&gt;Oh wait.&lt;/p&gt;

&lt;p&gt;You were on the production server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k_yBSwlF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/x52q68xv4mozpotnuobh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k_yBSwlF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/x52q68xv4mozpotnuobh.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;center&gt;"Maybe if I control-z I can undo it"&lt;/center&gt;

&lt;p&gt;This was just a hypothetical example, but it could happen! It's important to visually make your production servers distinct as to reduce the chance of error. Doing so is very easy, and can potentially stop a total catastrophe.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Tutorial
&lt;/h2&gt;

&lt;p&gt;Put the below line in your &lt;code&gt;~/.profile&lt;/code&gt; file:&lt;br&gt;
&lt;code&gt;export PS1="\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h.{{ domain }}\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ "&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;{{ domain }}&lt;/code&gt; with the name of your environment.&lt;/p&gt;

&lt;p&gt;Now you can see the environment in your prompt:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;caleb@web0.cloud20:~$&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For production environments at &lt;a href="https://15five.com"&gt;15Five&lt;/a&gt; we use a distinct color and put the environment name in uppercase:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export PS1="\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h.\[\033[01;31m\]{{ domain }}\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ "&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lKvKs3bs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fkl7s8el5yxbedzujfzx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lKvKs3bs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fkl7s8el5yxbedzujfzx.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feel free to customize this to your liking - you can even put emojis in your prompt!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yYZPFj2L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/54ozh3yim73qtbadig6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yYZPFj2L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/54ozh3yim73qtbadig6a.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can automate this for all your servers by using &lt;a href="https://github.com/ansible/ansible"&gt;Ansible&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# key_names is a list of users&lt;/span&gt;

&lt;span class="c1"&gt;# https://serverfault.com/questions/322997/how-do-you-make-it-obvious-you-are-on-a-production-system&lt;/span&gt;
&lt;span class="c1"&gt;# http://abload.de/img/bash-color-chartmxjbp.png&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set terminal prompt to have VPC name&lt;/span&gt;
  &lt;span class="na"&gt;lineinfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;dest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/home/{{ item }}/.profile&lt;/span&gt;
    &lt;span class="na"&gt;regexp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^export&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;PS1='&lt;/span&gt;
    &lt;span class="na"&gt;line&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;export&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;PS1="\[\e]0;\u@\h:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;\w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h.{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;domain&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"'&lt;/span&gt;
  &lt;span class="na"&gt;with_items&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;key_names&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
  &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;env_name != 'production'&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set terminal prompt to have red uppercase VPC name in production&lt;/span&gt;
  &lt;span class="na"&gt;lineinfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;dest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/home/{{ item }}/.profile&lt;/span&gt;
    &lt;span class="na"&gt;regexp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^export&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;PS1='&lt;/span&gt;
    &lt;span class="na"&gt;line&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;export&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;PS1="\[\e]0;\u@\h:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;\w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h.\[\033[01;31m\]{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;domain|upper&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"'&lt;/span&gt;  &lt;span class="c1"&gt;# noqa: 204&lt;/span&gt;
  &lt;span class="na"&gt;with_items&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;key_names&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
  &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;env_name == 'production'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  But what if I accidentally run Ansible against the wrong environment?
&lt;/h2&gt;

&lt;p&gt;You can catch that too by using a Ansible &lt;a href="https://docs.ansible.com/ansible/latest/plugins/callback.html"&gt;callback plugin&lt;/a&gt;! Assuming you have a environment variable in your terminal for the environment you are running against, you can verify that the Ansible inventory matches the environment variable.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;You probably have to adapt the file for how you handle secrets and deployments via Ansible.&lt;/p&gt;




&lt;p&gt;† Assuming your other servers are google DNS servers from the future that work with just 16 bits of storage. You know, the usual.&lt;/p&gt;

&lt;p&gt;Fun fact: You can actually &lt;a href="https://unix.stackexchange.com/a/101247/420478"&gt;recover data&lt;/a&gt; from a &lt;code&gt;rm -rf&lt;/code&gt;!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>sre</category>
      <category>tutorial</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
