Functions
UDCs have been renamed to Functions
Functions used to be called UDCs (User Defined Commands). Earthly 0.7 still uses COMMAND
for declaring functions, but the keyword is deprecated and will be replaced by FUNCTION
in Earthly 0.8.
Earthly Functions are reusable sets of instructions that can be inserted in targets or other functions. In other words, it is a way to import common build steps which can be reused in multiple contexts.
Unlike targets, functions inherit the (1) build context and (2) the build environment from the caller. Meaning that
Any local
COPY
operation will use the directory where the calling Earthfile exists, as the source.Any files, directories and dependencies created by a previous step of the caller are available to the function to operate on; and any file changes resulting from executing the function's commands are passed back to the caller as part of the build environment.
Thus, when importing and reusing functions across a complex build, it is very much like reusing libraries in a regular programming language.
Usage
Functions are defined similarly to regular targets, with a couple of exceptions: the name is in ALL_UPPERCASE_SNAKE_CASE and the recipe must start with COMMAND
(Note: this keyword will be replaced with FUNCTION
in Earthly 0.8). For example:
This function can be invoked from a target via DO
A few things to note about this example:
The definition of
MY_COPY
does not contain aFROM
so the build environment it operates in is the build environment of the caller.This means that
+MY_COPY
has access to the file./foo
.Although the copy file operation is performed within
+MY_COPY
, its effects are seen in the environment of the caller - so the resulting./bar
is available to the caller.
Scope
Functions create their own ARG
scope, which is distinct from the caller. Any ARG
that needs to be passed from the caller needs to be passed explicitly via DO +COMMAND --<build-arg-key>=<build-arg-value>
, as in the following example.
Global imports and global args are inherited from the base
target of the same Earthfile where the command is defined in (this may be distinct from the base
target of the caller).
Targets vs Functions
Targets and functions are Earthly's core primitives for organizing build recipes. They encapsulate build logic, and from afar they look pretty similar. However, the use-cases for each are vastly different.
In general, targets are used to produce specific build results, while functions are used as a way to reuse build logic, when certain commands are repeated in multiple places. As a real-world analogy, targets are more like factories, while functions are more like components that are used to put together factories.
Here is a comparison of the two primitives:
Targets | Functions | |
---|---|---|
Represents a collection of Earthly commands | ✅ | ✅ |
Can reference other targets in its body | ✅ | ✅ |
Can reference other functions in its body | ✅ | ✅ |
Build context | The directory where the Earthfile resides | Inherited from the caller |
Build environment, when no | Inherited from the base of its own Earthfile | Inherited from the caller |
| Inherited from the base of its own Earthfile | Inherited from the base of its own Earthfile |
| Creates its own scope | Creates its own scope |
Requires that | ✅ | ✅ |
Global | Inherited from the base of its own Earthfile | Inherited from the base of its own Earthfile |
Can output artifacts | ✅ | ❌ - can issue |
Can output images | ✅ | ❌ - can issue |
Can be called via | ✅ | ❌ |
Can be used in conjunction with an | ✅ - | ✅ - |
Commands that can reference it |
|
|
Last updated