Tommy LeeSoftware development for everyone else

Steps to Automation

Identify Steps that can be automated

Automation can be designed by breaking up a complex task into many, simple tasks. We can take a few tasks that can be seen as a manual process.

One of the following issues that I have is doing deployment for software. I also need to notify my monitoring service when a new software release occurred.

Problem: I need to deploy working software to my server.

Step 1. Generalize The Process

We can identify the basic steps required to update and change the current server software. In the simple deployment case, I see it work like this.

  1. Build Software
  2. Test Software
  3. Push New Build of Software to Server
  4. Run installations and changes on Server.
  5. Restart Service
  6. Notify Monitoring Service

So the flowchart looks like this:

Flowchart of the Steps listed above

Step 2. Breakdown Process into multiple Smaller Steps

So each of these steps have mini steps put together.

Build Software

  1. I take changes from my git repository and update to the newest version.
  2. I optimize any assets that need optimization. This includes images, or final CSS output.

Test Software

  1. I run any Integration tests to make sure there are no regressions.
  2. I run any Unit tests to make sure there are no regressions.

Push New Build of Software to Server

  1. I produce a package that I upload to one of my servers
  2. I unzip the package to the correct directory.

Run Installation and changes on Server

  1. I install any updated packages
  2. I Apply any schema migrations

Restart Services

  1. I restart the web and app services.

Notify Monitoring Services

  1. I Notify NewRelic that a new build has been launched.

Additional Steps as from above, with breaking down of each step

Step 3. Identify How to Trigger this Process

We have different ways to determine how automation should trigger. Currently we have these two types of events.

Time Based Processes

These are things that are meant to run on a schedule. They are triggered based on what time it is.

Examples:

  • Every week, rotate the log files.
  • Every 5 minutes, check if the service is online
  • On the first of every month, generate a report of user time and usage.

Event Based Processes

These are events that are triggered based on criteria.

Examples:

  • When I get an email, copy the subject line to a new file
  • When a User submits a form, write information to a database.
  • When code is submitted, run automated tests.

In our case, we

Step 4. Build steps using a Clean Room Approach

Strange Bug: Safari Parsing

So I spent half a day fixing the following errors. The layout on Rental Cars Search results have been broken on Safari. We suspected that this had to do with Safari's sppecific handling of divs and invalid HTML.

The General Setup

So the affected code in question looks like this. We have a homebrew JS template that looks and acts roughly like this.

<script type="text/template" id="rental-car-details">
    <div>
       ...
    </div>
</script>

... Somewhere in a JS file...

var details = $('#rental-car-details').clone();
...
details.replace("{{pricing}}", priceDetails);
...
resultsBody.append(details);

We have a template, and we build a DOM element, that gets injected after results come back from an AJAX request.

Check the Commit Logs

We confirmed with QA that this was a new bug. Checking the logs, we see only one major commit from the last valid section.

Test By Bisection

I reduced a lot of the code down to make sure that no other divs were affecting it. To make sure that the layout was stable even before this chunk of template exists.

Since this template is loaded via a template tag in Javascript. I started commenting out code and anything irrelevant, to find the part of the load that breaks the code.

The Cause

I started commenting out different parts of the template, and was able to identify the exact line of HTML that causes the problem.

This was that line

{{strike}}
<span class="actual-price">
    <span class="dollar">$</span>{{period_price}}
</span>
<span class="perday">/{{period.abbr}}</span>

So we kept pairing it down. to eventually get to:

<span class="dollar">$</span>

Yes, so while this is okay in most of the browsers, for some reason, in Safari. When this is injected, this breaks the layout.

Test cases for solutions.

So we did some small tests, seeing if it had something to do with the characters, or the signs. And what we came up was this:

<!-- This *somehow* fixes it -->
<span class="dollar"> $ </span>

<!-- This is still broken -->
<span class="dollar"> $</span>

<!-- This is still broken -->
<span class="dollar">$ </span>

So we found that Javascript Engine in Safari parses the >$< character incorrectly. It required atleast 3 characters within between the span.

Solution:

So to make the least breaking changes possible, I eneded up with the following.

<!-- Safari fix: single dollar sign ($) breaks layout. -->
<span class="dollar">&#36;</span>{{period_price}}

I would love to know why this breaks in Safari. But we'll have to investigate the root cause another day.

Cook and Code 3: Rabbit Season

This meetup was graciously hosted by Dmytro Malikov. He put on his own Cook and Code at his home, with a few of his coworkers here, Eric and Matt.

We tried to implement the single chef / sous chef during this cook and code.

Recipe

Dmytro suggested that we get adventurous, bringing Rabbit from this local latin market.

We ended up doing this recipe:

https://cooking.nytimes.com/recipes/12254-italian-style-braised-rabbit-with-rosemary-and-mushrooms

Snacks

Matt brought Chips and I prepared some Rosemary red potatoes. Really helped keep the motivation up while we tried to figure out the rabbit.

Struggles are real

So we had some issues following this recipe. This was my first time cooking rabbit, and I wasn't prepare to be a butcher. I forgot to carry my Dad's Heavy cleaver, and tried sawing away at the bones and spine. Since it was Dmytro's knife, I feared the back of the rabbit would snap the thin blade.

I had to call over Dmytro to handle the Rabbit. Snap, went the shoulders, the mid back and the hind legs. In my 10 minutes of fiddling, he tore through the bones in 45 grunt filled seconds.

Team Troubleshooting

Dmytro had a little CSS problem. We were able to cast it up on his projector and team debug it.

Results

I didn't think the Rabbit came out too well. Overcooked it. Even though it was my first rabbit. Jimmy made some backup ribs, and it went over well.

Cook and Code 2: Cooking Ribs

Cook and Code 2

As we make this a monthly tradition, we expndeda to having another member. This time around, we had DmytNro Malikov from Accenture come along.

Dish of the day: Apple flavored Baby Back Ribs

Part of Cook and Code is developing dishes that cook on their own while we spend our time on projects. Jimmy and Charlene brought a rack of baby back ribs, and plan to cook it in a pressure cooker pot.

Recipe

https://recipes.instantpot.com/recipe/easy-bbq-instant-pot-ribs/

We used a modification of the recipe above, but replaced water with apple juice and apple cider.

We did our best to keep everyone involved. Accompanying the ribs, Dmytro and I prepped some vegetable side dishes.

I love that cooking is an activity that everyone can participate. No matter what their skill level, we all have some experience in different areas of cooking.

Jimmy and Charlene had some minor difficulties in cleaning the ribs, pulling away the membrane on the underside. Dmytro, our resident expert in butchery, stripped the membrane cleanly and quickly with his knife skills.

Ribs in Pot

So Tender

The ribs came out very tender. Fell apart the bone. 10/10 would 1000% recommend.

For vegetables. I cooked up some sweet potato fries in the oven, as well as a slaw from Costco.

Ribs in Pot

Meetup Lessons Learned

As our second meetup, we picked up a few lessons to work on in future meetups.

  • Too many cooks
  • Too Complicated to make food
  • Bring Snacks
  • Time to Talk vs Time to Code

Issue: Too Many Cooks

We wanted to bring more focus on the working on the coding and the side projects. We had issues with people butting heads together and not having everything available for cooking available.

We're seeing this could lead to scalability issues.

Solution: Less Chefs

So instead of having everyone participate in the cook, we're going to try in the next Cook and Code having a dedicated chef.

We're calling this having a Lead Chef, Senior Chef as well as having an assistant chef or two.

Issue: Complex prep recipes

I'm used to spending a lot of time prepping and cooking, but this doesn't work well while we're trying to optimize for time. So from now on, we're trying to use a more simpler recipe to cook.

Solution: Simplified recipes

Simple enough. Make easier stuff, simpler items.

Issue: Time to Talk vs Time to Code

So there are some awkward moments where people weren't sure when it is a good time to talk, or focus on work. This occurred mostly during the early period of coding, or during cooking.

Solution: Dedicated Scheduling

So this was brought up by Jimmy. We probably need to have dedicated time slots so people know when to do what.

We built a template of the schedule, and try to adhere to it.

  • Social Periods: Intro and Eating. Talk as much as you'd like
  • Work Periods: Keep chit chat to relevant projects. Or take chats to IMs messaging instead. Follow the headset rules.

Selfie including Tommy

Cook and Code 1: Cooking and Coding Together

Cook and Code 1

So Jimmy Vo and I have a time management problem. We try our best to balance what time we have to:

  • Expand and maintain our social circle
  • Learn new tech stuff or work on side projects
  • Cook and learn more recipes

So he came up with this brilliant idea: A meetup dedicated to cook and code.

Introducing Orlando's Cook and Code Together

The concept is simple. Developers meet up. We prep some food together, then code. While the food is either marinating or cooking, we work on some personal development, with fellow developers nearby to bounce ideas or get assistance.

Meeting #1: Beef Burgundy

We chose a simple recipe, that takes a while to cook. I grew up eating my dad's beef burgundy. Sweet, rich, meaty stew that takes an entire day to cook.

We found a recipe that can be cooked within 3 hours. You can find it here:

Beef burgundy recipe

Cook and Code Raw Ingredients

We divided the labor so that everyone can get to cook asap. I chopped up the vegetables, while Jimmy browned the steak chunks. Browning the meat is important in stews, since it adds additional flavor, and preserves some of the texture.

Cook and Code Raw Ingredients

So we threw in all the vegetables, with the water and bottle of wine into a large pot, and left it to cook. I made sure that it didn't boil over and stirred it around occasionally.

Cook and Code Raw Ingredients

Coding Goals

For our coding session, we made goals that can be achieved by the end of the session. I try to use [S.M.A.R.T] goals as a framework of choosing what to complete.

For Jimmy, he's playing with Azure and working on hosting his website.

For me, I'm playing with React to create a form page for one of my side projects.

As with any learning experience, we ran into some issues. I ran into some issues with the ES6 Syntax and how CommonJS module loading works. Jimmy's azure account was having issues, and couldn't get access to the right areas for deployment.

Around the hour mark, I check on the stew.

Cook and Code Raw Ingredients

We decided to work on figuring out how to get Jimmy's project deployed. I remembered that .NET Core could be deployed on Ubuntu, so we went ahead and worked on some basic deployment on Ubuntu.

It was a great learning experience for Jimmy, since he's from a Windows shop. It was some configurations of nginx, and installing .NET Core CLI to the server.

Cook and Code Raw Ingredients

We pick up a lot of small, unwritten things when we work with others. We learn habits from our friends and family, lessons from our mistakes. I passed down some of my experience doing sysadmin stuff, and deploying stuff on Linux. We learned from repeated errors trying to get the site to run.

In cooking, I made a great mistake with the initial prep for the stew. Instead of seeing the meat slowly get softer, but remain in one piece, the meat started breaking apart. The sweet, winey liquid I expected was non-existent.

I forgot to coat the meat in flour.

So we had braised beef instead.

Cook and Code Raw Ingredients

Lessons Learned for a Successful Cook and Code

So with a completed work, and a full stomach, we call the inaugural Cook and Code Together a success! We learned some new recipes to serve and food prep, and expanded what we knew and had something to work towards in the future.

Some recommendations we have for others:

  • Choose a recipe you haven't tried yet
  • Divide the labor
  • Set measurable goals

Cook and Code Schedule Template

We follow the following time-line for most cook and codes.

  • 11:00 AM - Event Start and meal prep and cook. Social time and people get together.
  • 11:30 AM - Start coding. Waiting until the food is ready.
  • 02:00 PM - Food is served.
  • 03:00 PM - Clean up.

We have another cook and code coming up soon. We usually keep it small so that the group can work together well. While we can divide up the cooking for just one person, working together on the recipe lets everyone share in the experience.