Month: January 2023

Jud Flow

Jud Flow

Keeping a nice and tidy code repository makes me happy. Here’s the typical process I use to avoid messes:

  1. Create my-sweet-new-feature branch from main
  2. Make some awesome code edits, then commit them
  3. Make some slightly less awesome edits, commit them also
  4. Run some tests, nothing works; debug and commit the fix
  5. Decide my originally awesome code isn’t so awesome; rewrite the whole feature and commit
  6. Tests pass locally, yay! Push my-sweet-new-feature to Github and create a pull request
  7. Hrm, tests fail in pipeline; whoops, forgot a file; commit and repush
  8. Okay, tests pass now, so message team for review
  9. That’s a reasonable request, change made and committed
  10. Fine, we’ll use your naming convention; change made and committed
  11. Ugh, made a spelling error; committed
  12. Fixed moar typos
  13. Uggggggh, one last commit to fix spacing; pushed to Github
  14. Wha? Tests failing? :facepalm: forgot a file again
  15. Commit that file and push one last time for realz
  16. Tests pass, team reviews and approves, we’re good to go
  17. Pull an update of the main branch
  18. Come back to my-sweet-new-feature and rewrite all the commits on top of updated main; group edits into a clean subset of logical changes, one per commit, that makes it look like I wrote the code perfectly the first time, with nicely crafted commit messages that will mean something to some poor future developer that has to maintain my code ten years from now
  19. Run tests to ensure everything still passes; it does
  20. Force push to the pull request, obliterating all those ugly prior commits with these nice clean ones
  21. Try to merge the branch to main with fast-forward only option, forget that Github doesn’t support it (curse you Github! even flipping CodeCommit supports fast-forward only merging)
  22. Fast-forward merge my-sweet-new-feature to main locally so my final commit signatures are preserved
  23. Try to push main to Github, but it fails because the branch is protected
  24. Unprotect main temporarily, repush
  25. Dang it, someone merged new changes since step 17; repull main and rebase my branch
  26. Re-push my final changes and re-protect main

See how easy that is? No excuses moving forward, my friends!

All The Things

All The Things

I agree with this article that there’s a special joy that comes from building something to suit your own needs. But that doesn’t mean you shouldn’t share the results. You’ve got to store your artifacts somewhere, so might as well stick them in a public spot like Github. Perhaps someone else will find your work interesting and useful, not the least of whom might be an interviewer who needs examples of your code to do a proper evaluation.

Here’s a rundown of projects for which I am either the primary author or significant contributor, grouped roughly by subject matter. I capture them here for the value of having such an index, but also because some of it I believe has value. If any of you find such value, would you let me know?

Lambda Functions & Tools

Buy Me A Coffee Webhook – I wrote about this project two weeks ago, it’s a CDK-deployed Lambda function with an HTTPS endpoint that can receive webhook notifications from Buy Me A Coffee.

Temperature Collector – Another Lambda function, but this one deployed using terraform. It gathers temperature data from heterogeneous sources and publishes it to CloudWatch. I’ve also written about this one before; if nothing else it’s a reference example for how to use terraform modules.

Selenium Lambda Layer – It’s tricky to get all the right bits in place to get a headless browser working with Selenium in Lambda. Given how browser tech evolves, I doubt this still works, and if I have to do it again, my first choice would be CloudWatch Synthetics Canaries instead.

Lambda Layer Builder – When packaging dependencies, I prefer keeping them in a layer vs including them in the Lambda deployment package itself. It keeps the deployable package small, and ensures I can edit code directly in the console when I need quick turnaround. This script makes it a one-liner to construct and upload a layer that contains a set of either Python or Node.js dependencies.

Blockchain Constructs

Managed Blockchain Document Ledger – As part of a customer workshop I built this fully-functional example of using Amazon Managed Blockchain to write and read documents to Hyperledger Fabric. It illustrates how to create the network, set up users, load chaincode, front with an API Gateway and Lambda function, and deploy Hyperledger Explorer for visualizing the contents of the blockchain. It’s all automated using CDK and bash scripts.

Hyperledger Fabric CDK Construct – As I was developing the above, I realized there could be value in porting the capabilities provided by the bash scripts into custom resources, and packaging it all up into an easily installable CDK construct. This was my first foray into publishing a construct, and I learned a ton about it, in particular how to use projen to deploy a full CI/CD pipeline and get support across all CDK-supported languages.

Ethereum CDK Construct – Essentially the same as the above, but for Ethereum-based blockchain networks. I can only take minor credit for this one; while I gave them the idea, most of the implementation was done by an early career cohort as a capstone project.

Math, Music, and A/V Tools

Lilypond Music Files – Analogous to LaTeX for academic whitepapers, Lilypond is a text-based markup language for engraving (i.e. typesetting) sheet music. I created this repository as a place to collect my own by-ear transcriptions of bass guitar lines. There’s not much in there; consider it an aspirational life goal to add more (what would be extra rad is if this could be automated via AI/ML, with a tool like melody.ml).

Mix Maestro – I’ve been mixing live audio for nearly 20 years, on both analog and digital consoles. Back in 2013 I was doing so on a Roland mixer that had an RS-232 interface for remote control, and I wanted a way for musicians to adjust their own levels without buying an entire Aviom setup. So I grabbed a Raspberry Pi and wrote an HTTP server that abstracted the details. This repository contains the server code; I also wrote a companion Android app.

Light Maestro – Similar to Mix Maestro, I needed a way to control stage lighting, but without any budget to buy a console that had an app. Not only was I able to get a DMX interface built on top of another Raspberry Pi, but I was able to synchronize scenes to ProPresenter via its ability to trigger audio file playback, which I detected using Linux atime changes. Kinda hacky, but it worked more reliably than the bargain basement light board and the inexperienced volunteers that ran it.

Project Euler Solutions – If you want a fun and nerdy way to practice coding, Project Euler is a great resource (and more fun than Leetcode in this mathematician’s opinion). This repository contains my solutions to all the problems I’ve solved to date.

Docker Images

Buildozer – I love Python a lot, and sometimes that means I want to use it for projects where it isn’t typically considered, such as cross-platform GUI app development. With Kivy, it turns out to be quite possible. Buildozer is a framework for building Kivy apps for Android and iOS. Getting its dependencies right is a pain, especially on MacOS, but Docker to the rescue!

LaTeX – Back in graduate school I earned money by typesetting academic papers for mathematicians (such as the esteemed George Andrews) using LaTeX, a typesetting system built by none other than Donald Knuth, one of the giants of computer science (if you haven’t read The Art of Computer Programming, you really should; those folks were geniuses in ways modern developers rarely appreciate). Anyhow, LaTeX is also one of those tools that’s tricky to get set up, so it’s a perfect fit for running in Docker.

Development Utilities

AWS CLI Profile Credential Helpers – Early in my tenure with AWS, I was working with several customers simultaneously, each of which had its own single-sign on solution for their accounts (e.g. Azure SSO, Okta, Shibboleth). In order to abstract away the details of each provider’s mechanism for getting temporary credentials, I built this wrapper, along with a handful of other useful utilities. I’ve used them daily ever since.

Amazon CloudWatch Publisher – Another tool that came directly out of customer work, I needed a way to publish basic CloudWatch metrics (like CPU usage, disk space, network traffic) from Apple hardware, which would not (at the time) run the CloudWatch agent. I decided to build it in Python (natch), which has the added benefit of allowing it to run on other platforms such as the Raspberry Pi.

Kubernetes Tools – It took me a couple months of regular usage to get comfortable with kubectl. Once I could rattle off most commands from memory, I found myself doing similar things over and over. Hence these wrappers. I stuck them on Github for posterity, and am glad I did.

MacOS Dotfiles – Since I made the switch to MacOS (and its Linux-like terminal) in early 2014, I’ve had 4 employer owned and 2 personally owned Apple computing devices. Not changing that any time soon, and looking forward to a rumored 15″ Macbook Air, which I’ll probably buy for its portability (don’t really need the raw power of the Pro when I’ve got the cloud). When I do, I’ll use this set of scripts to automate its setup just how I like it.

Résumé Builder – An example of using LaTeX and my associated Docker image to build a PDF résumé via a continuous deployment pipeline implemented on Github and Travis CI. The résumé is the résumé, if you follow me?

Software Packages

Chrome Local Storage – Yet another project I’ve blogged about, this is a Python package for importing and exporting local storage from a Chrome browser. I built it to move Wordle stats from my laptop to my phone.

Output Scrubber – Writing sensitive information to application logs is generally a bad idea, but it’s easy to do so inadvertently. Include this package in your Node.js application, and it will insert itself into stdout and stderr and remove any pre-configured patterns it finds, such as social security numbers and email addresses. Of course if you’re logging in AWS, there’s some additional tools at your disposal.

Requestium – I’m not the original author of this package, but found its “best of both worlds” tremendously helpful when building some automation around an internal website, because it let me get logged in via Selenium and then switch over to the requests module to interact with APIs. When I needed a few new features, I offered to write the PRs, and discovered the creator was looking for a new owner for the project, and I decided to say yes, at least on a best effort basis. So far it hasn’t required more than a few hours a month at most.

Other Applications

Garage Envoy – This is another “build an HTTP API on top of a thing” project. I took a Raspberry Pi, added a relay that I wired into the opener, and some proximity sensors for detecting the position of the door, and voilà, I had an Internet controllable garage door. The most useful thing here was learning how to control the RPIO pins on the Pi to open/close switches and read sensor values.

Pinochle Scoresheet – In 2013 I went back to school to get a web development certificate from San Diego State. Part of that program was a class on Android app development, and this code was my capstone project. Pinochle is a card game that I’ve been playing since I was a kid, so it was fun to create an app I’d actually use. In retrospect, though, a native app is overkill and a simple mobile-friendly web app would be fine. Also, this app was Pinochle-specific, but I play quite a variety of games regularly, so a general-purpose tool would be nice to have…

Online Scoresheet (coming soon) – … thus this idea was born. Besides being an app I would use myself, I want to use this development to learn a few new things. First, I want to build it within a cloud-based integrated environment like Github Codespaces or Amazon CodeCatalyst. Second, I want to (finally) learn React.js beyond a hello world app. My domain name is bought (onlinescoresheet.net plus a few synonyms) and a sample app is spinning, all I need to do now is build it out.

Garbage In, Garbage Out

Garbage In, Garbage Out

I try to put as much code as I can on Github, as an exercise in learning in public. Over the holiday I published something new: a Lambda function deployed with CDK that is called when events fire from Buy Me A Coffee. It’s notable for a couple reasons:

  • First, if you haven’t noticed, there’s now a little orange icon down in the lower right of this blog. If you’ve benefited from my writings here, and are feeling generous, you can buy me a coffee using that icon. No pressure, though!
  • Second, I wanted a permanent reference repo for doing a basic Lambda deployment with CDK, and now I have one.
  • Finally, and most interestingly, my first draft of this code (both the CDK and the function itself) was written by ChatGPT.

As I’ve been reflecting on what artificial intelligence means for the future software engineering, I doubt it’s going to obviate the need for understanding code. What I do think it will be able to do is produce workable drafts, getting maybe half-way to a workable solution, with developers making revisions to get it across the finish line.

If I’m right about that, software professionals are going to need to tweak their skill sets to be less like writers and more like editors. Few developers I know are particularly adept at reading code, though it’s a shortcut for leveling up coding skill. Software is an oddball in that respect: in most other creative domains, one must study the work of the geniuses who came before, but we don’t typically train coders that way. Now it might not even matter, because the machines can do the studying for us.

What will be important, then? Formulating problems, and then tweaking resultant autogenerated code. So code fluency will still be needed. Just not for the boilerplate; for that, we’ll have tools like ChatGPT and AlphaCode.

Living On A Jet Plane

Living On A Jet Plane

Between a job requires a considerable amount of travel, and a whirlwind European vacation this summer, I’ve been to quite a few places this past year:

I’m thankful for the experiences I’ve had to date. Few things are more humbling than realizing that you are just one individual in a large world; I feel that way from my travels, and I’m far from having seen even a decent fraction of the cultures that fill the earth.

Want to be a better developer, manager, relative, friend, or person in general? Consider travel if you can.

Worth A Million Words

Worth A Million Words

The other day I posted a rundown of my work setup. I thought it’d be fun as a follow-up to give a demo of various microphone options I considered. Besides, you might not often get to see my face, and isn’t it more fun to show than tell?

Shokz OpenRun Pro (headset mic) – It’s mobile, but sounds terrible
Macbook Pro (built-in mic) – Ubiquitous and setup-free, but sounds muffled
Razer Kiyo Pro (webcam mic) – Better, but still a bit of background honkiness
Blue Yeti X (external mic) – Aww yeah, that’s what I’m talkin’ about

What do you think? At what point do you believe there are diminishing returns? Or do you disagree with my quality ordering altogether?

Oh, and for anyone wondering, the quote is from Confucius.

Gut Check

Gut Check

It’s that time again: New Year’s resolutions! Per my meta-resolution, this year’s book reading target is 44, but I wanted to add a twist to it.

Leaders who are right a lot “seek diverse perspectives and work to disconfirm their beliefs.” In 2022, 16 of the 45 books I read in were by authors who were either not male or not white. That’s 36%, a sizable fraction; in line with what I did in 2021 (33%) and 2020 (38%), and much better than my rates in 2019 (18%) and 2018 (15%).

But none of those metrics are anywhere close to reality: about 91% of the world’s population is either not male or not white. That’s a lot of valuable perspectives I’m missing out on.

Given my backlog and some strategic book choices I have lined up, getting all the way to 40 out of 44 isn’t realistic, but I can still do better than my recent history. So in 2023, my plan is to double last year’s fraction to 32 out of 44 (73%). Ambitious but doable. And I can’t wait.

Already finished my first one, in fact: Radical Candor. And I’m a chapter into The Analects, by Confucius. It’s embarrassing that I’ve never read anything by this giant of ancient wisdom. Already found a couple sayings that stand out:

The Master acquires his information by being affable, kind, and respectful, and by showing restraint in his action and a willingness to yield. The way the Master asks for information is different from that of other people.

Do not worry that other people do not know you. But be concerned that you do not know them.

Good stuff!

Tools Of The Trade

Tools Of The Trade

I’ve been working primarily from home since early 2019, and over time have carefully crafted a space that suits my needs pretty well. Here’s what I’ve put together, roughly from left to right as pictured:

Tuft and Needle California King mattress: Sleep is critical to success at work (and life in general). Upgrading to a big bed was a game changer, I can’t believe it took 21 years of marriage to take that plunge. Worth every penny.

Washburn 12 string acoustic guitar: My wife bought this for me for our first Christmas together in 1998. I’m not much of an acoustic player, but I can strum a few chords now and then.

Carvin Bunny Brunel signature 5 string bass: I’ve been playing bass for about 8 years, first on a Gretsch Junior Jet small scale, and then on this considerable upgrade.

Gallien-Krueger MB 112 combo amp: For a couple years I played through a hand-made German tube amp paired with a classic Ampeg 8×10 refrigerator-sized speaker cabinet that I refurbished myself. It was loud as heck and cool to look at, but weighed over 200 pounds and barely fit in my largest car. The tube amp was also finicky and I once shocked myself on its 220V power input (not fun). I’ve never regretted selling it and picking up this lightweight combo and its companion extension cab (not pictured). Just as powerful, better sounding, 20% the weight and volume, and more reliable. A no-brainer.

Casio Privia PX-130 digital piano: In 2010 I was on a short-term assignment 2500 miles from home, and needed something productive to do during my downtime. Bought this instrument and had it shipped to my extended stay hotel; it was just what the doctor ordered. The assignment ended up becoming a full-time gig, the one that led me to relocate from Ohio to San Diego. One of my better life decisions.

Picasso’s The Old Guitarist (not pictured): The art in the photo is some generic thing we bought when relocated, I don’t even remember where from. So I’d rather talk about the artwork you can’t see here, but will see in the background if you’re on a video call with me. It’s a print of my wife’s favorite painting. Also in the room are a pencil drawing of a character from the Wingfeather Saga that I commissioned the author’s son to make, and handwritten lyrics from one of my favorite Andy Gullahorn songs.

Jarvis Standing Desk from Fully: I’ll never willingly go back to a regular desk after enjoying the benefits of an adjustable height desk. I stand about 80% of the time now. And this desk was the perfect size, don’t really need a lot of space beyond what’s needed for my computer workstation.

Varier Variable Balens kneeling chair: Definitely overpriced given I stand most of the time, but given how unhealthy sitting is, when I’m not standing, I quite like kneeling. It also functions well on carpet, and tucks away nicely, both of which matter in a bedroom-based workspace.

Macbook Pro 16″ 2019: Haven’t used a Windows PC since 2012, and won’t ever go back. Would prefer native Linux, but I can still do enough terminal-based things to make it feel Unix-like. Upgrading to 32GB of RAM and going back to physical function keys would be nice but I’m fine for now.

Dell UltraSharp 34 Curved USB-C Monitor: Absolutely love only needing to plug in a single cable into my laptop for data and power, and the integrated USB ports mean no additional docking station is needing. Five years ago I would have wished for more resolution (and likely a second monitor), but training myself to organize my active work across multiple desktops obviated that need, and the screen itself is plenty wide for two windows side-by-side. As an aside, anyone who still insists on 80 character limits for code line length needs to be sent back to 1998; silliest linter default setting ever.

Logitech MX Mechanical Mini keyboard: The loud clickity-clack would get annoying in an office, but I’m by myself all day, so I’m loving it. The layout isn’t quite the same as the keyboard on the laptop itself, which is a tiny bit annoying, but I’ve adjusted.

Logitech MX Master 3S mouse: Lots of buttons and scroll doohickeys, fully programmable, feels great in the hand. Especially love that I can activate mission control with one press; really helps keep my windows organized.

Razer Kiyo Pro webcam: I spend a good portion of my day on video calls, including ones with customers with whom I need to earn trust. Every bit of quality matters when trying to communicate, thus a high-quality webcam that works in a variety of lighting conditions (I’m often on calls early in the morning before the sun is up). Sadly their software doesn’t work on Mac, but I can still tweak the settings with CameraController.

Blue Yeti X microphone: Audio quality probably matters even more than video quality when it comes to projecting trustworthiness and authority, thus I didn’t scrimp. With the boom arm I’m able to position the mic so it’s just out of the frame of the webcam. I’m not going for streamer or podcast vibes, I want the focus on my message, not the gear.

Shokz OpenRun Pro mini headphones (not pictured): Having a mic like the Yeti X means I can’t play call audio through speakers or listeners will hear feedback. That means using headphones. But I don’t want something bulky or that draws attention to itself. These are barely visible, sound sufficiently good for voice, have a battery that lasts darn near forever, and the open design means I can go between taking calls and hearing what’s going on around me at will. As the name implies, they’re also great for exercise. For music, and when I need isolation, my Sony WH1000XM4 headphones are vastly better, but they’re not nearly as convenient for every day wear.

Timbuk2 San Francisco backpack: I’m due for an upgrade here, but for now this gets the job done. What’s more important is what I keep in it at all times:

  • One each of a black, blue, and red pen, a 0.5mm mechanical pencil, and a small tablet of paper
  • Dual-ended whiteboard markers (blue, red, black, and orange)
  • USB-C to video adapter (includes HDMI, DVI, and VGA because you never know)
  • Nekteck 107W USB-C Charger with a 10 ft power cord (love this thing and its 4 ports)
  • Anker portable battery, and various USB power cables, enough to adapt between C, A, and micro-B as needed
  • USB-A to Apple lightning cord (I don’t have an iPhone, but I want to be helpful if others need one)
  • Extra charging cable for my watch and my headset (both of which are proprietary)
  • Toothbrush, toothpaste, floss, breath mints, deodorant, moist hand wipes, napkins, and a couple masks
  • Advil, Aleve, cold medicine of some kind, sunscreen, chapstick, and earplugs
  • Small stack of business cards
  • Travel umbrella

Thanks for reading all the way to the end of this monster post. Happy New Year to ya!