Build System: CI and Reproducible Local Builds with Earthly
Opened this issue · 0 comments
Earthly is a system designed to make local development builds behave in the same way as cloud CI build processes. Described as what would happen if Dockerfiles and Makefiles had a baby, it's basically like a container-based build system, except one that is designed specifically for producing an artefact that can run just as easily on the local filesystem at the end. You get a reproducible build, but then can debug the binary in your IDE with your local source folder easily.
It essentially wraps around an existing container runtime to add some features to it, that aren't possible if you e.g. just call docker build -f MyProject.Dockerfile
- much the same way github actions are really bog-standard container builds but wrapped in some extras. The idea is that normally, most CI processes have to write this logic manually - Earthly replaces a layer of manual shell scripts, etc. between the container engine and the language-specific buildtool.
You can see an example of what a simple Earthfile looks like here, and if like me, unfortunately you have nothing better to do whilst you wash up, you can listen to a video here that explains some of the motivation behind why the tool was developed and what it can do for us.
Or just enjoy this meme :)
It also adds some advanced caching options, both for local and cloud use, that can speed up builds quite significantly - unlike with a Dockerfile alone, you can say, install a new dependency early in the process, but if only one source file has changed, then Earthly will see the cached objects and (e.g. Make) will only rebuild that one object file and relink the final executable.
Cross-compilation is also meant to be relatively easy with Earthly, meaning that a local developer can work on their code, debug the problems, then rest assured that
- the build they have just produced locally will complete the same way when run in the cloud as part of CI
- the build they have just produced will also build successfully on other platforms.
I haven't tried this yet, but aim to give it a whirl soon.
Like anything, it's not perfect and comes with its own set of quirks. The examples often use say Go or rust, that have self-contained buildsystems, and so will always be relatively easy. C++ builds are obviously never straightforward and so my Earthfiles have sometimes bloated to accommodate different issues as they arise. This is probably something that needs fixed elsewhere in the chain however.
However, I can attest that it has made life easier when it comes to building projects, and especially when it comes to debugging them, allowing me to keep dependencies self-contained but not needing to debug something in a container jail (which is a pain). I generally aim to use it for all projects going forward that I start.
Given some of my own builds recently worked fine for me on my linux machine, but failed the CI process - which I couldn't run in my fork, because there are tokens and secrets necessary for uploading the output that I quite rightly don't have access to, I'd like to explore the possibility of switching the Neuromore build process (to be able) to use Earthly. I say this way, because it acts as a separate stage - for anyone who doesn't want to or can't run it, Earthly will be calling into the existing Makefiles in just the same way as one can do on their host OS. It's not going to stop anyone from building without using Earthly, but it would mean developers then have the option of replicating what will happen in the CI build so that they can verify their changes work (on multiple platforms), for any developer who wants to do it this way.
Github Actions are provided for Earthly, so if people are on-board with the idea of exploring this, I would like to start in my own fork by essentially migrating the Linux github action workflow from the individual manual steps specified in the YAML to be essentially:
- Clone and check out
- Earthly build
- Upload artefacts
Without those secrets, I don't think I can test the full workflow - but then, that's the benefit! Because I can do half of the work locally and know it should work the same in the cloud. It may make sense at that point to merge the fork into a working branch in the main repository and you can test with those tokens and rework as fit.
I already have a working Earthfile for Neuromore - in fact, the contents were originally pasted from the Ubuntu actions YAML - so I would simply neaten this up and go from there. I would start just with Linux AMD64, and look to merge this so that it can be put through its paces, before trying my hand at cross-compiling for other OSs and architectures.
Any thoughts?