Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Air – Live reload when developing with Go (github.com/cosmtrek)
117 points by justinclift on July 31, 2021 | hide | past | favorite | 45 comments


I built something like this in Go a few years ago but it reloads your infrastructure when it changes, recompiles your code when it needs to, and syncs static files or interpreted files to wherever your app is running (desktop or cloud). Think of it like docker-compose but with file watching + sync + smart rebuilds. https://skaffold.dev/


One of my most used tools. Absolute joy to work with it and its Helm integration.


Is there a skaffold for borg that inspired this? Curious if there are any existing things you were inspired by, or particular pitfalls in alternatives you wanted to avoid!


No but I heavily drew from three tools:

(1) minikube, which I also maintained at Google. I saw how difficult getting started with Kubernetes could be even when you were able to create a local cluster. I also knew all the shortcuts that you could take to streamline local Kubernetes workflows (e.g., loading images directly into the minikube docker daemon).

(2) docker compose, which remains a great tool but had no analogue for Kubernetes. It also didn't have a concept of syncing for hot-reloadable projects or built-in file watcher.

(1), Draft by the Deis folks at Microsoft, which was a great tool but suffered from having a component that you needed to install on the cluster to work, where the skaffold architecture was purely client side (making it a lot easier to get started, and faster). I also wanted to make skaffold pluggable, so it supported helm, kubectl, docker, bazel, and other tools right from the start. It also had clear boundaries between build and deploy and ideas for CI and gitops workflows built in.


Skaffold makes bringing up and down a complex stack on Kubernetes a breeze. Thank you for an awesome tool!


You're the author of Skaffold? Damn that's impressive


How does it handle watch mode for compiled or built code?


It parses a Dockerfile (or queries dependencies in a tool like bazel) to get a list of file dependencies and then kicks off an optimized rebuild and redeploy. If you're using buildkit and caches this can be done really quickly (close to native compile without a Docker image)

You can tell it to just sync certain changes (e.g. syncing a javascript file to a container running webpack).


http://eradman.com/entrproject/

  find . -name "*.go" | entr -r go run my/main/file.go


That can’t handle file creation after the command is run, though, right?


I'm not sure about "find" -- but I also use "entr" for this (and just about a billion other tasks, is there anything you can't use it for?) and I personally do something like:

  ls src/**/*.filetype | entr -r -s "some command"
And this will catch new files


How is it going to catch new files? ls runs once, doesn't it?


Awesome


`man entr` has an example for dealing with new files using the `-d` option:

    $ while true; do ls src/*.rb | entr -d make; done


When writing go, I've always found if I find myself constantly restarting & recompiling a program during development, it means that I should be writing tests instead.


Suppose you want to instrument some code that touches a database, because you suspect some data (in prod) is coming off the database that is messing your assumptions up, but you don't know yet what specific assumption it is.

Because it's just a gut feeling, you can't write a test against it


How would you write the tests to see if the RTL text is being displayed properly on the GUI when switching between LTR and RTL layout mode?

How would you write the tests to see if the GLSL shader is displaying the mesh on the screen with the correct gamma correction factor?


Given go's nature of being more network oriented, I think these questions are a bit disingenuous.

Go comes with a lot of facilities for testing the things it's good at.

If testing GLSL shaders, or gui applications is difficult, I'd consider putting at least some pressure on the tooling providers to provide better testing facilities.

I'm more familiar with how opengl & shaders work than I am with text rendering - so I'll keep my commentary towards the shader question. At least on the surface it seems de-composable into two distinct problems: Is the shader emitting the correct colors after gamma correction is applied, and is that rendering appearing on the screen.

The former could be tested by rendering to a buffer and capturing the output, and asserting against an expected color value.

The latter is where I'd say that better tooling is indeed required.


Ah the typical answer when TDD advocates get challenged at conferences regarding UI testing.

Advocacy works great when only data structures get tested.


I lnow you're saying that when it comes to GUIs you have to do it manually, but as someone working on the back-end this begs the question: is there no unit tests framework or anything for GUIs ?


Depends if we are talking about native or web based GUIs, and then the best you can get is automating the user clicking buttons and if the UI changes in some limited ways.

There is no way to properly test UI/UX experiences, even if the test is correct for a button being displayed with the right label, doesn't mean it looks correctly from user experience point of view, yet the test is green.


Taking repeated screenshots of a GUI and making sure they don't change across commits is a useful thing to have in CI a lot of the time to make sure if you did change something somebody's eyeballed it for correctness.

However I'm not at all claiming that removes the 'eyeballed it' step, just that it makes it harder to miss said step :)


I'm expecting someone to train a ML model soon to interpret and score GUIs.

"This page is confusing" and "This page no clear call to action" And "This page is ugly" And "This button doesn't look like a button."


For native Android apps there is a framework to do GUI tests. The test code stayed in your release as a NOOP last time i looked at it, may be fixed now.


There are, but nothing really satisfactory to be honest. GUI testing is still an unsolved problem in my book.


Write a test that launches the application and checks relevant pixels, at the very worst. Which is not generally all that hard. Bonus points if you save the full image so you can see expected / actual results easily.


Yep it’s actually one of the things i love. If waiting for go compile time has gotten to be a problem it is time for tests or to refactor if a test can’t be easily written.


Goes for just about any language tbh.


Does live-reload that runs tests exist?


If you write your tests with Ginkgo [0] its CLI can do this for you.

It also has nice facilities to quickly disable a test or portion of a test by prepending an X to the test function name, or to focus a test (only run that test) by prepending an F. It’s pretty nice.

[0]: https://onsi.github.io/ginkgo/


If it can watch files and trigger your app to boot it can certainly trigfer the test runner.



this is just a fancy description for a basic rollout system.


In my projects I use a script to watch for changes and recompile/restart with a loop such as:

  executable=/path/to/target
  while true; do
      make build
      if [ ${?} -eq 0 ]; then
          ${executable} run &
          pid=${!}
      fi
      inotifywait -qq -e create -e modify -e delete --exclude '\.#.*' -r .
      [ -n "${pid}" ] && kill ${pid}; pid=
  done
This is simplified a bit, as the script usually contains some other things like starting and initializing the database.


The best tool I’ve found for this job is reflex[1]. It’s easy to setup, Go agnostic, very « UNIX » in its philosophy, doesn’t get in your way with its own logs, and just works.

Before that I used realize but it has the bad behavior of always adding it’s own prefix to the logs, which sucks.

[1]: https://github.com/cespare/reflex


We use watchman with our Go apps: https://facebook.github.io/watchman/docs/install.html

It's straightforward to use but also has a ton of options so you can do whatever you want with it. It also handles common issues you'll run into when working with larger codebases where you end up watching over too many files. And finally, it has configuration files so you can have the same setup as the rest of the engineers on your team.

More importantly, it's actively maintained and has been out for a while, and it's not specific to Go apps: you can use it for anything you want to watch and execute on.


Useful tool, but it has some bugs related to consecutive build failures. Restarting Air is required to fix it. I still use it, just wish I didn't have to restart it frequently.


Air also needs be restarted if you're switching git branches and there are a lot of changes between the branches


Shameless plug, but I built https://github.com/superhuman/lrt as simply as possible, explicitly to avoid this kind of issue (which seem to plague tools in this space).


Here's my simple live reload that's generic enough for any language for me

```

filewatcher --immediate --restart "*/*.go" "killall ${BINARY_NAME}; make run"

```


I used docker + realize for the exact same task (go + gin) a year ago.

Wish I heard of air or skaffold. Didn’t find them when searching around this issue.


I can recommend https://github.com/cortesi/modd, it seems like its not developed anymore though


I've found it simple enough to start a goroutine to watch argv[0] and exec it if it's newer than the startup time of the process.

Unlike other languages with insane build and link times, I've never needed this for Go. Builds are nearly instantaneous.


This doesn't watch the fs and build automatically now.. Does it?

We started using this tool a couple of months ago. It was a huge productivity boost. We had multiple binaries produced by the build and all had to run to make the complete service


I usually run "go build" to see if my code compiles and respond to the errors. If it builds successfully, it's restarted automatically.

I personally don't see value in running "go build" out-of-band in another terminal where I can't easily pipe the errors into my editor (or automatically if I'm running it in the editor).

If that works for you, then great.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: