“Men, det funker jo på min maskin!”

Dette har du vel sikkert både hørt og opplevd. Vi utvikler features lokalt, og så oppfører det seg annerledes i prod. Det kan være en myriade av årsaker til dette, men har du ikke samme stack lokalt som i prod, så er du nesten garantert en overraskelse nå og da. Byggeverktøy hjelper oss masse med biblioteker, men hva med byggeverktøy selv?

Problemet er at noen av hovedverktøyene vi bruker, f.eks. runtime plattformen og kompilator gjerne må installeres separat. Og etter at vi fikk homebrew og tilsvarende verktøy, er disse verktøyene bare en “brew install” unna. Det er jo hendig, men det du får er gjerne siste versjon. Det er neppe versjonen appen din bruker. Antakeligvis har prosjektet en readme fil som forteller hvilke versjoner du skal bruke. Å sette riktig versjon kan være slitsomt å få til, spesielt med verktøy som homebrew. Vi utviklere er late, så det som er slitsomt blir som regel ikke gjort…

Vi er i 2022, det må da finnes en bedre løsning.

La meg vise deg!

➜  code: brew install asdf
...
To use asdf, add the following line to your ~/.zshrc:
  . /usr/local/opt/asdf/libexec/asdf.sh

Restart your terminal for the settings to take effect.

zsh completions have been installed to:
  /usr/local/share/zsh/site-functions

➜  code: echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ${ZDOTDIR:-~}/.zshrc

➜  code: source ~/.zshrc

➜  code: asdf
version: v0.9.0

Ok, kjapt å sette opp. Mitt oppsett er altså homebrew med zsh, viktig at dette blir riktig, så bruk offisiell dok.

La oss se hva asdf kan hjelpe med.

➜  code: git clone https://github.com/kodemaker/kodemaker.no
Cloning into 'kodemaker.no'...
remote: Enumerating objects: 21367, done.
remote: Counting objects: 100% (1775/1775), done.
...

➜  code: cd kodemaker.no

➜  kodemaker.no git:(master) ✗ cat README.md
...
Skaff [leiningen](https://github.com/technomancy/leiningen#leiningen) om du ikke
har den. Sats på versjon 2.9+. Hvis du har en gammel versjon under 2.0 så funker
det garantert ikke. På OSX kan du hente den med homebrew: `brew update && brew
install leiningen` eller med SDKMAN: `sdk install leiningen`

Du må også ha JDK 1.11. Sjekk med `java -version`, ellers
[last ned her](http://www.oracle.com/technetwork/java/javase/downloads/index.html) eller installer med SDKMAN.
...

Måtte lete litt, men her har jeg jo infoen som må til. Da jeg jeg prøvde å starte med det jeg allerede hadde, fikk jeg en feil. La oss teste ut asdf.

➜  kodemaker.no git:(master) asdf plugin-add java https://github.com/halcyon/asdf-java.git

➜  kodemaker.no git:(master) asdf list all java
...
openjdk-10.0.2
openjdk-11
openjdk-11.0.1
...

➜  kodemaker.no git:(master) asdf install java openjdk-11
####################################################################################################################################################################################################################################### 100.0%
openjdk-11_osx-x64_bin.tar.gz
openjdk-11_osx-x64_bin.tar.gz: OK

➜  kodemaker.no git:(master) asdf local java openjdk-11

➜  kodemaker.no git:(master) ✗ java -version
openjdk version "11.0.6" 2020-01-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.6+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.6+10, mixed mode)

Tøft, det var jo kjapt å installere riktig jdk. Så hva det leiningen da, kanskje det funker på samme måte?

➜  kodemaker.no git:(master) asdf plugin-add lein https://github.com/miorimmax/asdf-lein.git

➜  kodemaker.no git:(master) ✗ asdf list all lein
...
2.9.6
2.9.7
2.9.8

➜  kodemaker.no git:(master) ✗ asdf install lein 2.9.8

➜  kodemaker.no git:(master) ✗ lein -version
No version is set for command lein
Consider adding one of the following versions in your config file at /Users/stoyle/projects/repos/code/kodemaker.no/.tool-versions
lein 2.9.8

➜  kodemaker.no git:(master) ✗ asdf local lein 2.9.8
Leiningen 2.9.8 on Java 11.0.6 OpenJDK 64-Bit Server VM

Ok, leiningen kom jo kjapt. Da er det vel bare å kjøre opp da vel?

➜  kodemaker.no git:(master) ✗ lein ring server
Downloading Leiningen to /Users/stoyle/.lein/self-installs/leiningen-2.9.8-standalone.jar now...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   663  100   663    0     0   2334      0 --:--:-- --:--:-- --:--:--  2334
100 12.2M  100 12.2M    0     0  9560k      0  0:00:01  0:00:01 --:--:-- 16.3M
/Users/stoyle/.lein/self-installs/leiningen-2.9.8-standalone.jar.pending: OK
...

[app] Created database in 1427 ms
[app] Created web app in 7222 ms
[app] Ingested all data in 5244 ms
[app] Started watcher in 292 ms
Started server on port 3334

Up and running, det var jo enkelt! Hvordan ser repoet mitt ut nå mon tro?

➜  kodemaker.no git:(master) ✗ git status
On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	.tool-versions

nothing added to commit but untracked files present (use "git add" to track)

➜  kodemaker.no git:(master) ✗ cat .tool-versions
java openjdk-11
lein 2.9.8

Aha! Det var dette denne asdf local ... kommandoen gjorde. En fil på rota av prosjektet som definerer hvilke verktøy jeg skal bruke her.

Ok, hva om prosjektet allerede har en sånn fil? La meg vise! Her et “hello world” prosjekt i elixir på erlang/beam:

cd hello

➜  hello: cat .tool-versions
erlang 24.2
elixir 1.12.3

➜  hello: mix
No preset version installed for command elixir
Please install a version by running one of the following:
asdf install elixir 1.12.2
or add one of the following versions in your config file at /Users/stoyle/projects/repos/code/hello/.tool-versions
elixir 1.13.2-otp-24
elixir 1.12.3

Ok det var jo behjelpelig. Jeg har allerede noe installert, så enten kan jeg endre .tool-versions, eller bare installere den som noen andre har valgt. Prøver på siste, jeg.

➜  hello: asdf install elixir 1.12.2
==> Checking whether specified Elixir release exists...
==> Downloading 1.12.2 to /Users/stoyle/.asdf/downloads/elixir/1.12.2/elixir-precompiled-1.12.2.zip
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:-  0     0    0     0    0     0      0      0 --:--:-- --:-100 5908k  100 5908k    0     0  18.3M      0 --:--:-- --:--:-- --:--:-- 18.2M
==> Copying release into place

➜  hello: mix -v
Erlang/OTP 24 [erts-12.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]
Mix 1.12.2 (compiled with Erlang/OTP 22)

Ah så deilig, kjapt og enkelt, og jeg trengte ikke en gang sjekke readme! Faktisk hadde det holdt å skrive asdf install, så ville alle eventuelle versjoner jeg mangla blitt installert.

Hva med globalt oppsett

Veldig ofte så er det ønskelig at tooling er tilgjengelig over alt. Dette har selvsagt asdf en løsning for. Her ønsker jeg å kjøre node et tilfeldig sted, der jeg ikke har en .tool-versions fil.

➜  hello: cd ..

➜  code: node
No version is set for command node
Consider adding one of the following versions in your config file at
nodejs 14.16.0
nodejs 16.13.2

Ok, jeg har to versjoner installert, men ingen av dem gjelder. Vi prøver å sette versjon globalt.

➜  code: asdf global nodejs 16.13.2

➜  code: node -v
v16.13.2

➜  code cat ~/.tool-versions
nodejs 16.13.2

asdf leter altså etter en .tool-versions fil under hjemmeområde, og der settes globale versjoner, hendig!

Den store fordelen!

Å lese readme og installere for hånd er slitsomt. Så hvorfor ikke bare la asdf si ifra om du mangler noe. Bytter du mellom prosjekter, der du allerede har riktige versjoner installert, så får du automagisk riktig versjon, ingen installasjon påkrevd.

En annen stor fordel er at du her har ett verktøy å lære deg, og det funker likt for alle plugins det støtter, og det er en del.

Dette er jo veldig kjekt for en selv da, men hva med i teamet? Dersom du skal bumpe en sdk, hvordan kommuniserer du til teamet at det skal oppdateres? Etter min erfaring må man oppdatere readme, og så må man mase på alle om at de må oppdatere. Du er heldig om dette blir gjort. Et års tid senere, så kommer noen til å klage på at “det funker ikke på min maskin”, de har typisk ikke oppdatert.

Dersom alle bruker asdf så er det rett og slett bare å endre i .tool-versions, så vil dine team-medlemmer oppdatere med en gang de får endringen.

Prøv asdf, nok et lite verktøy som gjør livet litt enklere!