Coder Social home page Coder Social logo

cloud-issues's Introduction

Earthly

Earthly
It’s like Docker for builds

GitHub Actions CI Join the chat on Slack Docs Website Install Earthly Docker Hub License MPL-2

Open in GitHub Codespaces

πŸ” Repeatable Builds - Write builds once, and run them anywhere – on your laptop, remote, and in any CI.

❀️ Super Simple - Instantly recognizable syntax – like Dockerfile and Makefile had a baby.

πŸ›  Compatible with Every Language, Framework, and Build Tool - If it runs on Linux, it runs on Earthly.

🏘 Great for Monorepos and Polyrepos - Organize your build logic however makes the most sense for your project.

πŸ’¨ Fast Builds - Build caching and parallel execution makes builds fast automatically.

♻️ Reuse, Don't Repeat - Never write the same code in multiple builds again.


🌎 Earthly is a versatile, approachable CI/CD framework that runs every pipeline inside containers, giving you repeatable builds that you write once and run anywhere. It has a super simple, instantly recognizable syntax that is easy to write and understand – like Dockerfile and Makefile had a baby. And it leverages and augments popular build tools instead of replacing them, so you don’t have to rewrite all your builds no matter what languages you use.


Get Earthly

Table of Contents

Why Use Earthly?

πŸ” Repeatable Builds

Earthly runs all builds in containers, making them self-contained, isolated, repeatable, and portable. This allows for faster iteration on build scripts and easier debugging when something goes wrong – no more git commit -m "try again". When you write a build, you know it will execute correctly no matter where it runs – your laptop, a colleague’s laptop, or any CI. You don’t have to configure language-specific tooling, install additional dependencies, or complicate your build scripts to ensure they are compatible with different OSs. Earthly gives you consistent, repeatable builds regardless of where they run.

❀️ Super Simple

Earthly’s syntax is easy to write and understand. Most engineers can read an Earthfile instantly, without prior knowledge of Earthly. We combined some of the best ideas from Dockerfiles and Makefiles into one specification – like Dockerfile and Makefile had a baby.

πŸ›  Compatible with Every Language, Framework, and Build Tool

Earthly works with the compilers and build tools you use. If it runs on Linux, it runs on Earthly. And you don’t have to rewrite your existing builds or replace your package.json, go.mod, build.gradle, or Cargo.toml files. You can use Earthly as a wrapper around your existing tooling and still get Earthly’s repeatable builds, parallel execution, and build caching.

🏘 Great for Monorepos and Polyrepos

Earthly is great for both monorepos and polyrepos. You can split your build logic across multiple Earthfiles, placing some deeper inside the directory structure or even in other repositories. Referencing targets from other Earthfiles is easy regardless of where they are stored. So you can organize your build logic however makes the most sense for your project.

πŸ’¨ Fast Builds

Earthly automatically executes build targets in parallel and makes maximum use of cache. This makes builds fast. Earthly also has powerful shared caching capabilities that speed up builds frequently run across a team or in sandboxed environments, such as Earthly Satellites, GitHub Actions, or your CI.

If your build has multiple steps, Earthly will:

  1. Build a directed acyclic graph (DAG).
  2. Isolate execution of each step.
  3. Run independent steps in parallel.
  4. Cache results for future use.

♻️ Reuse, Don't Repeat

Never have to write the same code in multiple builds again. With Earthly, you can reuse targets, artifacts, and images across multiple Earthfiles, even ones in other repositories, in a single line. Earthly is cache-aware, based on the individual hashes of each file, and has shared caching capabilities. So you can create a vast and efficient build hierarchy that only executes the minimum required steps.

Where Does Earthly Fit?

Earthly fits between language-specific tooling and the CI

Earthly is meant to be used both on your development machine and in CI. It runs on top of your CI/CD platform (such as Jenkins, Circle CI, GitHub Actions, and GitLab CI/CD). Earthly provides the benefits of a modern build automation system wherever it runs – such as caching and parallelism. It is a glue layer between language-specific build tooling (like maven, gradle, npm, pip, go build) and CI, working like a wrapper around your build tooling and build logic that isolates build execution from the environments they run in.

How Does It Work?

In short: containers, layer caching, and complex build graphs!

Earthly executes builds in containers, where execution is isolated. The dependencies of the build are explicitly specified in the build definition, thus making the build self-sufficient.

We use a target-based system to help users break up complex builds into reusable parts. Nothing is shared between targets other than clearly declared dependencies. Nothing shared means no unexpected race conditions. In fact, the build is executed in parallel whenever possible, without any need for the user to take care of any locking or unexpected environment interactions.

ℹ️ Note Earthfiles might seem very similar to Dockerfile multi-stage builds. In fact, the same technology is used underneath. However, a key difference is that Earthly is designed to be a general-purpose build system, not just a Docker image specification. Read more about how Earthly is different from Dockerfiles.

Installation

See installation instructions.

To build from source, check the contributing page.

Quick Start

Here are some resources to get you started with Earthly

See also the full documentation.

Reference pages

A simple example (for Go)

# Earthfile
VERSION 0.8
FROM golang:1.15-alpine3.13
RUN apk --update --no-cache add git
WORKDIR /go-example

all:
  BUILD +lint
  BUILD +docker

build:
  COPY main.go .
  RUN go build -o build/go-example main.go
  SAVE ARTIFACT build/go-example AS LOCAL build/go-example

lint:
  RUN go get golang.org/x/lint/golint
  COPY main.go .
  RUN golint -set_exit_status ./...

docker:
  COPY +build/go-example .
  ENTRYPOINT ["/go-example/go-example"]
  SAVE IMAGE go-example:latest
// main.go
package main

import "fmt"

func main() {
  fmt.Println("hello world")
}

Invoke the build using earthly +all.

Demonstration of a simple Earthly build

Examples for other languages are available in the examples dir.

Features

β›“ Parallelization that just works

Whenever possible, Earthly automatically executes targets in parallel.

Demonstration of Earthly's parallelization

πŸ’Ύ Caching that works the same as Docker builds

Cut down build times in CI through shared remote caching.

Demonstration of Earthly's caching

πŸ›  Multi-platform support

Build for multiple platforms in parallel.

VERSION 0.8
all:
    BUILD \
        --platform=linux/amd64 \
        --platform=linux/arm64 \
        --platform=linux/arm/v7 \
        --platform=linux/arm/v6 \
        +build

build:
    FROM alpine:3.18
    CMD ["uname", "-m"]
    SAVE IMAGE multiplatform-image

🀲 Build tools that work everywhere

No need to ask your team to install protoc, a specific version of Python, Java 1.6, or the .NET Core ecosystem. Install once in your Earthfile, and it works for everyone. Or even better, you can just make use of the rich Docker Hub ecosystem.

VERSION 0.8
FROM golang:1.15-alpine3.13
WORKDIR /proto-example

proto:
  FROM namely/protoc-all:1.29_4
  COPY api.proto /defs
  RUN --entrypoint -- -f api.proto -l go
  SAVE ARTIFACT ./gen/pb-go /pb AS LOCAL pb

build:
  COPY go.mod go.sum .
  RUN go mod download
  COPY +proto/pb pb
  COPY main.go ./
  RUN go build -o build/proto-example main.go
  SAVE ARTIFACT build/proto-example

See full example code.

πŸ“¦ Modern import system

Earthly can be used to reference and build targets from other directories or even other repositories. For example, if we wanted to build an example target from the github.com/earthly/earthly repository, we could issue

# Try it yourself! No need to clone.
earthly github.com/earthly/earthly/examples/go:main+docker
# Run the resulting image.
docker run --rm earthly/examples:go

πŸ”¨ Reference other targets using +

Use + to reference other targets and create complex build inter-dependencies.

Target and artifact reference syntax

Examples

  • Same directory (same Earthfile)

    BUILD +some-target
    FROM +some-target
    COPY +some-target/my-artifact ./
  • Other directories

    BUILD ./some/local/path+some-target
    FROM ./some/local/path+some-target
    COPY ./some/local/path+some-target/my-artifact ./
  • Other repositories

    BUILD github.com/someone/someproject:v1.2.3+some-target
    FROM github.com/someone/someproject:v1.2.3+some-target
    COPY github.com/someone/someproject:v1.2.3+some-target/my-artifact ./

πŸ”‘ Cloud secrets support built-in

Secrets are never stored within an image's layers and they are only available to the commands that need them.

earthly set /user/github/token 'shhh...'
release:
  RUN --push --secret GITHUB_TOKEN=user/github/token github-release upload file.bin

FAQ

How is Earthly different from Dockerfiles?

Dockerfiles were designed for specifying the make-up of Docker images and that's where Dockerfiles stop. Earthly takes some key principles of Dockerfiles (like layer caching) but expands on the use cases. For example, Earthly can output regular artifacts, run unit and integration tests, and create several Docker images at a time - all outside the scope of Dockerfiles.

It is possible to use Dockerfiles in combination with other technologies (e.g., Makefiles or bash files) to solve such use cases. However, these combinations are difficult to parallelize, challenging to scale across repositories as they lack a robust import system, and often vary in style from one team to another. Earthly does not have these limitations as it was designed as a general-purpose build system.

For example, Earthly introduces a richer target, artifact, and image referencing system, allowing for better reuse in complex builds spanning a single large repository or multiple repositories. Because Dockerfiles are only meant to describe one image at a time, such features are outside the scope of applicability of Dockerfiles.

How do I know if a command is a classic Dockerfile command or an Earthly command?

Check out the Earthfile reference doc page. It has all the commands there and specifies which commands are the same as Dockerfile commands and which are new.

Can Earthly build Dockerfiles?

Yes! You can use the command FROM DOCKERFILE to inherit the commands in an existing Dockerfile.

build:
  FROM DOCKERFILE .
  SAVE IMAGE some-image:latest

You may also optionally port your Dockerfiles to Earthly entirely. Translating Dockerfiles to Earthfiles is usually a matter of copy-pasting and making minor adjustments. See the getting started page for some Earthfile examples.

How is Earthly different from Bazel?

Bazel is a build tool developed by Google to optimize the speed, correctness, and reproducibility of their internal monorepo codebase. The main difference between Bazel and Earthly is that Bazel is a build system, whereas Earthly is a general-purpose CI/CD framework. For a more in-depth explanation see our FAQ.

Contributing

  • Please report bugs as GitHub issues.
  • Join us on Slack!
  • Questions via GitHub issues are welcome!
  • PRs welcome! But please give a heads-up in a GitHub issue before starting work. If there is no GitHub issue for what you want to do, please create one.
  • To build from source, check the contributing page.

Licensing

Earthly is licensed under the Mozilla Public License Version 2.0. See LICENSE.

cloud-issues's People

Contributors

alexcb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

elicharlese

cloud-issues's Issues

Idea: self-hosted satellites

It would be great to have the ability to self-host satellites. It could still be a paid feature but being able to host those ourselves would make me feel much more comfortable using them

Offer Satellites In More Regions

Offering satellites in more regions would help our users bring the build closer to their CI and/or local operations. SemaphoreCI, for example. apparently operates in the EU.

How to TRIGGER on push/PR to any branch?

From TRIGGER docs it seems the pipeline could only been triggered by a particular branch. Is there a way to trigger on any branch?

One use-case for that is preview deployments - deploying every branch on every change to dev server so QA/design/others don't need to pull and build locally. For example Gitlab has it for years and nowadays calls it Review apps.

Unable to remove member from org if they are admin

A customer discovered that running earthly org member rm <email address> returns a 500 error if the user has admin permissions.

They found a workaround on their own. They changed the user's permissions to "read" and then were able to remove them.

earthly org member update --permission read <email address>
org member rm <email address>

There are a couple of options I can think of that might improve the user experience:

  1. Allow the removal of an admin as long as there's at least one other user with admin permissions.
  2. Display a better error message (in either case) that also suggests the workaround.

Confusing auth error when user does not have access to PROJECT declared in Earthfile.

An Earthly CI customer (new employee) was trying to run an Earthfile locally that works for other team members and in CI within the org. He was seeing this error:

Error: build target: build main: failed to solve: Earthfile line 98:4 apply FROM earthly/dind:alpine: resolve image config for earthly/dind:alpine: unauthorized

The Earthfile has a PROJECT declaration and the user had not been invited to the org. Once he was added it worked fine as expected. This error message was confusing however because 'earthly/dind:alpine' is a public image. Also, I would expect the error message to let the user know that they don't have access to the org/project (or even say the project does not exist for security reasons).

Satellite-level permissions

Users have requested both the ability to give users permissions to manage satellites. It's also been requested that some satellte-level permission could also be useful, for example, a CI runner that only a single CI account is allowed to run things on.

Build fails in CI but not locally or with Satellites

Below is the error that is causing the build in CI to fail. This works locally and with Satellites.

Failures:
   1958  
   1959   g/s/m/:efb5c51+test *failed* |   1) Contract lifecycle with RLS Creates a contract
   1960   g/s/m/:efb5c51+test *failed* |      Failure/Error: expect(page).to have_css(".id", exact_text: contract.id)
   1961   g/s/m/:efb5c51+test *failed* |        expected to find css ".id" but there were no matches
   1962  
   1963   g/s/m/:efb5c51+test *failed* |      [Screenshot Image]: /app/tmp/capybara/failures_r_spec_example_groups_contract_lifecycle_with_rls_creates_a_contract_662.png
   1964  
   1965  
   1966   g/s/m/:efb5c51+test *failed* |      # ./spec/system/contract_spec.rb:94:in `block (3 levels) in <top (required)>'
   1967   g/s/m/:efb5c51+test *failed* |      # ./spec/system/support/better_rails_system_tests.rb:20:in `block (2 levels) in <top (required)>'

The full build logs: https://ci-beta.earthly.dev/builds/354da12d-6457-4bcd-8f49-7d8ea70796a9

CI Error displaying logs

While testing with ARGS I got this result from a CI run:

image

The error that should have been displayed is (by running the CI's target locally):

Error: build target: build main: failed to solve: async earthfile2llb for ./quote_client/+docker: quote_client/Earthfile line 21:2 copy artifact: apply bui
ld +build: earthfile2llb for +build: quote_client/Earthfile line 12:2 apply ARG: value not supplied for required ARG: base_url
in              github.com/earthly/earthly-solutions/examples/polyrepo/quote_client:main+build --base_url=
in              github.com/earthly/earthly-solutions/examples/polyrepo/quote_client:main+docker --tag=test1

Fixing the pipeline was easy given the error message. We should look into why it had trouble showing this error in CI.

Add organization delete command.

There is currently no way to delete an organization from the CLI. It would be nice to make deleting organizations simpler.

Something like: earthly org rm <org-to-delete>

earthly satellite hangs (for 15 minutes) after waking up

When using a satellite that has recently gone to sleep, the first time using it once it wakes up will hang for 15 minutes while attempting to pull an image.

for example:

              alpine | --> Load metadata alpine linux/amd64
             ongoing | alpine (16 minutes ago)        <--- this will hang
                 +ip | --> FROM alpine

after 15 minutes, buildkit reattempts the stuck connection, and it succeeds.

reproduction case

consider a basic Earthfile:

VERSION 0.7

ip:
  FROM alpine
  RUN apk add curl
  RUN --no-cache curl -s http://icanhazip.com

and a runner script:

#!/bin/sh
set -ex
earthly=earthly-v0.7.0-rc3

org="earthly-technologies"
sat="alex-test"

date
"$earthly" --satellite "$sat" +ip

date
"$earthly" sat --org "$org" sleep "$sat"

date
sleep 60

date
"$earthly" --satellite "$sat" +ip

date

the buildkit logs will produce:

time="2023-02-16T20:51:55Z" level=debug msg="session finished: <nil>"

... satellite goes to sleep, then wakes up ...

time="2023-02-16T20:53:53Z" level=debug msg="session started"
time="2023-02-16T20:53:53Z" level=debug msg=resolving host=registry-1.docker.io
time="2023-02-16T20:53:53Z" level=debug msg="do request" host=registry-1.docker.io request.header.accept="application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, */*" request.header.user-agent=buildkit/v0.6 request.method=HEAD url="https://registry-1.docker.io/v2/library/alpine/manifests/latest"

... then after roughly 15 minutes...

time="2023-02-16T21:10:19Z" level=debug msg="fetch response received" host=registry-1.docker.io response.header.content-length=157 response.header.content-type=application/json response.header.date="Thu, 16 Feb 2023 21:10:19 GMT" response.header.docker-distribution-api-version=registry/2.0 response.header.docker-ratelimit-source=35.160.176.56 response.header.strict-transport-security="max-age=31536000" response.header.www-authenticate="Bearer realm=\"https://auth.docker.io/token\",service=\"registry.docker.io\",scope=\"repository:library/alpine:pull\",error=\"invalid_token\"" response.status="401 Unauthorized" url="https://registry-1.docker.io/v2/library/alpine/manifests/latest"
time="2023-02-16T21:10:19Z" level=debug msg=Unauthorized header="Bearer realm=\"https://auth.docker.io/token\",service=\"registry.docker.io\",scope=\"repository:library/alpine:pull\",error=\"invalid_token\"" host=registry-1.docker.io

... then the connection gets reattempted

time="2023-02-16T21:10:19Z" level=debug msg="do request" host=registry-1.docker.io request.header.accept="application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, */*" request.header.user-agent=buildkit/v0.6 request.method=HEAD url="https://registry-1.docker.io/v2/library/alpine/manifests/latest"

... and it works

time="2023-02-16T21:10:20Z" level=debug msg="fetch response received" host=registry-1.docker.io response.header.content-length=1638 response.header.content-type=application/vnd.docker.distribution.manifest.list.v2+json response.header.date="Thu, 16 Feb 2023 21:10:20 GMT" response.header.docker-content-digest="sha256:69665d02cb32192e52e07644d76bc6f25abeb5410edc1c7a81a10ba3f0efb90a" response.header.docker-distribution-api-version=registry/2.0 response.header.docker-ratelimit-source=2b697055-3ede-42a8-a8ce-addb3ad1c7fb response.header.etag="\"sha256:69665d02cb32192e52e07644d76bc6f25abeb5410edc1c7a81a10ba3f0efb90a\"" response.header.strict-transport-security="max-age=31536000" response.status="200 OK" url="https://registry-1.docker.io/v2/library/alpine/manifests/latest"

... and proceeds to download data
time="2023-02-16T21:10:20Z" level=debug msg=resolved desc.digest="sha256:69665d02cb32192e52e07644d76bc6f25abeb5410edc1c7a81a10ba3f0efb90a" host=registry-1.docker.io
time="2023-02-16T21:10:20Z" level=debug msg=fetch digest="sha256:69665d02cb32192e52e07644d76bc6f25abeb5410edc1c7a81a10ba3f0efb90a" mediatype=application/vnd.docker.distribution.manifest.list.v2+json size=1638

In another case, the request failed, after 15 minutes, with a different error message:

time="2023-02-16T19:24:09Z" level=error msg="/moby.buildkit.v1.frontend.LLBBridge/ResolveImageConfig returned error: rpc error: code = Unknown desc = failed to do request: Head \"https://registry-1.docker.io/v2/library/alpine/manifests/latest\": dial tcp: lookup registry-1.docker.io on 127.0.0.11:53: server misbehaving"

Built-in Pull-Through Cache

Satellites or CI runs could utilize Earthly's own Pull-Through cache, by-passing the need to use Docker Hub as heavily and getting rate-limited by their free Docker account.

Satellites sleep when not in use to save costs

To save on user's compute costs, Satellites should go into a "sleep" state while they are not in use.

The Satellite will enter its sleep state after ~30 minutes have passed since the last finished build. While in a sleep state, the user is not billed for any compute minutes.

The Satellite remains in its sleep state until a new build is started, at which point, the Satellite will automatically wake back up, and Earthly will wait a moment for the Satellite to finish starting. This is indicated to the user during the init phase of an Earthly build.

Screen Shot 2022-10-28 at 9 16 48 AM

Users can also check if a Satellite is awake or asleep by running the earthly satellite inspect command. When the Satellite is Operational, Earthly will connect to the underlying Buildkit instance and display its information. When the Satellite is reported as Sleeping, however, the inspect command will not attempt the Buildkit connection.

Screen Shot 2022-10-28 at 9 12 24 AM

The user can force a sleeping Satellite to wake up using a new earthly satellite wake command. Calling wake when a Satellite is already awake will simply extend the Satellite's active time by another 30 minutes before it attempts to go back to sleep. Note that the wake command can also be used to force a Satellite back into an Operational state, should there ever be an issue that results in the Satellite entering a bad state.

Expose detailed satellite usage metrics to users

  • Satellite users wishing to optimize and right-size their satellites need a way to capture telemetry (CPU, memory, iops, storage).
  • Ideally, telemetry from satellites could be integrated with popular observability tools (DataDog, Prometheus) in a low-friction way.

Registry auth fails if more than one registry is added in Earthly CI

A customer setup Earthly CI with his Docker Hub credentials. He then later added is Github container registry credentials. His builds on Earthly CI started failing with 403 errors anytime they pulled images from ghcr.io. Once he removed his Docker hub credentials, it started working.

Earthly CI build hangs in Github Check API

These may be an artifact of the way Earthly CI used to work when it first came out of alpha...

  • An alpha customer had an Earthly CI build hang (it was stuck in the running state for 2+ weeks. This is the one you commented on in community slack @mikejholly)
  • On the Github Check status page for their repo - it also shows the Earthly job still running (for over 18 days I think).
  • @vladaionescu hypothesized that we may need to make an API call to Github to actually stop the build from showing as running in Github Actions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.