Slide 1

Slide 1 text

Date Writing a modern CLI tool. Henrique Vicente 27th July, 2016

Slide 2

Slide 2 text

Originally I/O happened via a physically connected system console. Then…

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

From Time-sharing to today’s iTerm ✤ Type on the terminal
 
 cat ~/Downloads/behind-the-firewall.gif | imgcat

Slide 5

Slide 5 text

IBM XT ✤ First computer coming with standard hard- drive

Slide 6

Slide 6 text

Classic hypothetical program 1. Takes an input 2. Does some magic 3. Writes to output

Slide 7

Slide 7 text

POSIX real world program ✤ Standard in / out streams (stdin, stdout, stderr) ✤ Environment variables ✤ Working directory ✤ Arguments ✤ Exit code ✤ parent process, process id, process group,

Slide 8

Slide 8 text

What you want ✤ Static binaries ✤ Easy and secure distribution channel ✤ Easy to program ✤ Garbage collection ✤ High-level programming language ✤ Modern, clean, safe (type safety) ✤ Avoid the hype (unless if its arguments win) ✤ Lightweight startup for short-lived processes ✤ Great performance for long-lived daemons ✤ Reliable tests ✤ Culture ✤ No unbundled or dynamically linked dependencies ✤ No interpretation or virtual machines ✤ Trustworthy dependency managing

Slide 9

Slide 9 text

stdout and stderr unexpected merging issues

Slide 10

Slide 10 text

stdout and stderr unexpected merging issues ✤ ordering sort (e.g., verifying what is printed on tests) ✤ "updating" output (i.e., progress bar) modifying what you get

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

What about the children?

Slide 13

Slide 13 text

Child processes ✤ Zombies, orphans… ✤ Quite hard to work with
 reapers, actually.

Slide 14

Slide 14 text

From “gh” to “we”

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

Maintenance hell ✤ No tests ✤ Node.js 0.8 was still borning, API changes ✤ dumb npm packages… left-pad ¯\_(ツ)_/¯ ✤ dependency hell ✤ callback hell: no Promise() ✤ At certain point [I thought?] people hated me

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

Choosing a language for WeDeploy’s CLI

Slide 19

Slide 19 text

Build one pet project before committing to an unfamiliar language or ecosystem ✤ I wrote picel: is a light-weight, blazing fast* REST-ful micro service for image processing with a lean API https://github.com/henvic/picel on my own time
 
 After feeling comfortable with it, I sold the idea of building the we CLI tool
 
 
 * this statement isn't guaranteed.

Slide 20

Slide 20 text

Static executable binaries = less headaches ✤ No dependency hell ✤ No virtual machines ✤ Implication: disadvantage for interpreted languages

Slide 21

Slide 21 text

Why not C ✤ No protection against programmer mistakes ✤ No code coverage suite for high-level programming ✤ Pointers are too low level (memory based, not object based) ✤ Supporting different platforms is a hell.

Slide 22

Slide 22 text

Why not Bourne shell ✤ Environment ✤ No code coverage tool ✤ External dependencies hell (curl, etc) ✤ Performance ✤ OS X stuck in outdated 9 years old bash (shame on you, GNU GPLv3)

Slide 23

Slide 23 text

Why not JavaScript (ES6 + Node.JS) ✤ Almost good enough, but… ✤ Environment hell ✤ V8 virtual machine is light-weight, but not light enough ✤ requiring files is not cheap ✤ Dependency hell ✤ Can't trust npm today (and probably not in anything less than 5-years)

Slide 24

Slide 24 text

Why not Java, Scala, or… ✤ JVM ✤ Performance ✤ Lack of culture for this use-case ✤ Not trivial to try new things (Java 8 is way better, actually)

Slide 25

Slide 25 text

Why not Python, Ruby, or interpreted ones… ✤ Almost good enough, but… ✤ Environment hell ✤ Versioning issues (less dramatic than Node) ✤ Less files to require than npm ecosystem, still some… ✤ Dependency hell ✤ Why bother with runtimes?

Slide 26

Slide 26 text

LLVM is a killer compiler infrastructure… Why not Swift? ✤ A really serious competitor to Go on this area, but…
 
 Ecosystem is missing, hence couldn't even consider.

Slide 27

Slide 27 text

Go for-the-win ✤ Emerging, proven language by Google ✤ docker, Kubernetes, and many other great tools are written in Go ✤ ______ is written in Go ✤ Sexy syntax, simple API ✤ Garbage collected, small static binaries

Slide 28

Slide 28 text

Programming in Go vs. Node.js ✤ Static binaries vs. Environment nightmare ✤ Lean garbage collector vs. Virtual machine weight ✤ Almost no experience vs. Quite experienced ✤ Reliable, above average quality dependencies vs. lots of dependencies ✤ Powerful, above average quality built-in dependencies vs. fewer ✤ Compiled, better performance vs. interpreted, high startup cost for CLI tools ✤ Go routines easier concurrency support vs. Promises, events

Slide 29

Slide 29 text

Infrastructure & tests ✤ Complexity tests (unchecked errors, CRAP, etc) ✤ Missing documentation ✤ Unit tests ✤ Integration tests (simulated environment) ✤ Functional tests (real environments, can destroy things)

Slide 30

Slide 30 text

Configuration ✤ .ini format >> JSON, JSON 5, XML, etc.

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

Commands, subcommands, flags, persistent flags, suggestions, help command auto generation… ✤ You want all that: use a framework ✤ Don't forget about autocompletion

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

Autocompletion ✤ several levels of completeness and trade-offs ✤ from easy to very complex… ✤ zsh's autocomplete is very powerful:
 http://zsh.sourceforge.net/Doc/Release/Completion-System.html ✤ asking yourself: support autocomplete on what shells?
 zsh? bash? fish?

Slide 35

Slide 35 text

Simple autocompletion for bash [and zsh trough plugin] ✤ Add hidden "we autocomplete" command ✤ Traverses all commands and flags, filtering by arguments ✤ Prints out an output command or flag per line ✤ Uses custom function (next slide) to add dead simple (but limited) autocomplete functionality ✤ Works on bash natively ✤ Doesn't work on fish ✤ Works on zsh with plugin (bash_complete for zsh) we autocomplete script loads

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

ANSI escape code (colors, bold, italic…) ✤ You don't have to use rainbows. 256-color and even 24 bit true color support is possible nowadays on some shells, but your user loses control and you don't want it ✤ Remember you don't have exact control over the color palette your users use for ANSI colors. Just expect green to look green and red to look red. Not #ff0000 or #cc0000 or whatever you use ✤ Don't use fancy experimental features such as opening images on the terminal unless you like death threats (or have an experimental use case)

Slide 38

Slide 38 text

“oh, it compiles for Windows. So, I am going to setup a SSH server on a Windows 10 vm and all should work”… Except… ✤ Good luck with setting up a nice SSH setup on Windows with keys and everything.
 95 > 10 ⇒ Windows 95 > Windows 10 ✤ Good luck with autocomplete (kidding, just forget about') ✤ Wait, where are my colors? What are these weird characters?
 "fix": —no-color by default ✤ 10+ consoles: cmd, PowerShell, PowerCmd, cygwin, bash, …
 All inconsistent with each other (or it wouldn't be Windows) ✤ new bash support solves everything (just kidding - it's a lie) ✤ Everything can go goes wrong

Slide 39

Slide 39 text

How to distribute? ✤ curl | bash issues: security, errors, etc. ✤ need solid, replicable, release procedures to avoid breaking production (which you don't have control, probably) ✤ need auto-update strategy that doesn't suck

Slide 40

Slide 40 text

Release procedure ✤ git status should report directory is clean ✤ check for unchecked errors ✤ check for code issues and defects ✤ run tests (but functional) ✤ run tests (but functional) on a docker instance ✤ run functional tests on OS X, Linux, and Windows virtual machines ✤ ask for a release tag ✤ edit release tag message ✤ publish (if for the stable channel, publish on unstable actually) ✤ push tag to GitHub ✤ download release and run functional tests on OS X, Linux, and Windows virtual machines ✤ if for the stable channel, publish (promote) release [from the unstable] to the stable channel ✤ if for the stable channel, download release and run functional tests on OS X, Linux, and Windows virtual machines to report any abnormalitiesa

Slide 41

Slide 41 text

Questions?

Slide 42

Slide 42 text

Images ripped from ✤ https://en.wikipedia.org/wiki/System_console ✤ https://commons.wikimedia.org/wiki/File:IBM_1620.jpg ✤ https://commons.wikimedia.org/wiki/File:ASR-33_at_CHM.agr.jpg ✤ https://commons.wikimedia.org/wiki/File:Ibm_px_xt_color.jpg ✤ https://www.youtube.com/watch?v=RybNI0KB1bg ✤ https://en.wikipedia.org/wiki/File:Graveling.jpg ✤ http://deadlikeme.wikia.com/wiki/Dead_Like_Me_Wiki ✤ https://lastlog.de/blog/posts/nodejs_on_nixos_status.html ✤ http://maxogden.com/nested-dependencies.html