basics:
- OS: FreeBSD everywhere desktop laptop & servers
- FreeBSD jails and zfs snapshots for lighweight testing and deployment
- dtrace on FreeBSD and recon for debugging and tracing BEAM apps live. I’ve never needed pry & friends.
- haproxy on my computer to redirect http requests and databases to whatever jail is actually running at that time
- urxvt terminals appropriately titled for the task at hand, i3 for window manager, fish shell
- devel/zeal: an offline docs browsing tool
- git-cola: super graphical git commit tool for unix
BEAM
- lang/elixir, rebar, rebar3, mix, hex all installed from FreeBSD packages
- installed lang/erlang, erlang-runtime19, erlang-runtime20, lang-erlang-runtime21 all from packages (yes you can have them concurrently installed)
- I switch between the erlang versions with a simple
set PATH /usr/local/lib/erlang20/bin $PATH
where needed. I cannot tell you how nice this is.
- the packages are upgraded regularly usually 1-2 days after official OTP and elixir releases so you’re always patched without stress
editor
- neovim with vim-plug, alchemist, vim-mix, vim-mix-format, network, a bunch of std tpope vim plugins (commentary, fugitive, sensible, projectionist), all the vim-erlang/* plugins, rainbow, vim-better-whitespace, ctrlp
- I also have intellij-ultimate which I use for “larger” project management - moving stuff between files, its nice to use the mouse with tabs and many files sometimes
comms
- irc via irccloud.com or hexchat
- slack & hipchat for work-related stuff
workflow
I typically have a couple of windows open - a running elixir app on the left pane in a while loop, so I just need to ctrl-C to have it restart if needed.
mix clean; while mix format
iex --name hive --cookie yum -S mix
clear
end
and in that one I use ConCache to “copy” interesting data from the running program into the iex repl to play with. I often have network ports and pids in the values, so having real ones to play with is critical. this looks like this:
iex(hive@wintermute.skunkwerks.at)4> conn = ConCache.get(:webhook_cache, :req)
%Plug.Conn{
adapter: {Plug.Adapters.Cowboy.Conn,
{:http_req, #Port<0.1471292>, :ranch_tcp, :keepalive, #PID<0.18751.0>,
"POST", :"HTTP/1.1", ...
iex(hive@wintermute.skunkwerks.at)6> conn |> Plug.Conn.get_req_header("x-real-ip")
You can then do all the nice stuff right there in the repl! When I have the rough form of the desired function or module working, I switch over to vim in the right side window, write tests around my desired behaviour, throw in the code from IEx into a module, and profit.
The conn above is captured using a little Plug I shift around inside the app while I’m fiddling:
defmodule CapnHook.Debug do
@moduledoc """
Pretty Print the conn with nice colours
"""
@highlighting [number: :yellow, atom: :cyan, string: :green, nil: :magenta, boolean: :magenta]
use Plug.Builder
def call(conn, _opts) do
ConCache.put(:webhook_cache, :conn, conn)
IO.inspect(conn, label: __MODULE__, syntax_colors: @highlighting, width: 0)
conn
end
end
In my final pane, I run a syslog tail on top, and a small window on bottom with mix test --trace --no-deps-check --stale
until it’s all good.
then switch over to git-cola, order some smaller commits, do the distillery dance to produce a release, and I have a small script that turns that tarball into a deployable FreeBSD package.
If anybody’s interested in more details, message me, and I’ll spin this into an actual blog post.