Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
a035401
Consolidate several small scripts into a single __tool
vector-of-bool Oct 29, 2025
5f4b103
Significant Earthfile refactor
vector-of-bool Oct 29, 2025
7b73e94
Update Earthly-generated tasks
vector-of-bool Oct 30, 2025
c22a137
Simplify some path handling in Earthfile
vector-of-bool Oct 30, 2025
f488eab
Fix: Allow Ccache to cache properly in Earthly targets
vector-of-bool Oct 30, 2025
358a337
Split out an +init target
vector-of-bool Oct 30, 2025
ec044b1
Update Earthly target documentation
vector-of-bool Oct 30, 2025
e5d322f
Rearrange some Earthly documentation
vector-of-bool Oct 30, 2025
31e88f8
Fix: Wrong build paths to +verify-headers
vector-of-bool Oct 30, 2025
bdd5741
Add Ubuntu 24.04
vector-of-bool Oct 30, 2025
71ffffc
Enable building both with/without Snappy in Earthly
vector-of-bool Oct 30, 2025
1f7d32a
Tasks with/without Snappy
vector-of-bool Oct 30, 2025
082ca14
Merge branch 'master' into CDRIVER-6142-earthfile-refactor
vector-of-bool Nov 10, 2025
e2308aa
Minor commentary tweaks following PR comments
vector-of-bool Nov 11, 2025
59829fc
Add a trailhead for obtaining the detailed Earthfile documentation
vector-of-bool Nov 12, 2025
9a6eb17
Refactor Earthly C++ installation to rely on the same C compiler param
vector-of-bool Nov 12, 2025
0a5ba4f
Fix environment setup when the C package provides C++
vector-of-bool Nov 12, 2025
f0c64eb
Better documentation on the __tool script
vector-of-bool Nov 12, 2025
d43510e
Drop use of Yum in __install
vector-of-bool Nov 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 62 additions & 40 deletions .evergreen/config_generator/components/earthly.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,27 @@

T = TypeVar('T')

_ENV_PARAM_NAME = 'MONGOC_EARTHLY_ENV'
_ENV_PARAM_NAME = 'MONGOC_EARTHLY_FROM'
_ECR_HOST = '901841024863.dkr.ecr.us-east-1.amazonaws.com'
_CC_PARAM_NAME = 'MONGOC_EARTHLY_C_COMPILER'
'The name of the EVG expansion for the Earthly c_compiler argument'


EnvKey = Literal[
'u20',
'u22',
'almalinux8',
'almalinux9',
'almalinux10',
'alpine3.19',
'alpine3.20',
'alpine3.21',
'alpine3.22',
EnvImage = Literal[
'ubuntu:20.04',
'ubuntu:22.04',
'ubuntu:24.04',
'almalinux:8',
'almalinux:9',
'almalinux:10',
'alpine:3.19',
'alpine:3.20',
'alpine:3.21',
'alpine:3.22',
'archlinux',
'centos9',
'centos10',
'quay.io/centos/centos:stream9',
'quay.io/centos/centos:stream10',
]
"Identifiers for environments. These correspond to special 'env.*' targets in the Earthfile."
'Base environment images to be built.'
CompilerName = Literal['gcc', 'clang']
'The name of the compiler program that is used for the build. Passed via --c_compiler to Earthly.'

Expand All @@ -51,53 +52,66 @@
"Options for the TLS backend configuration parameter (AKA 'ENABLE_SSL')"
CxxVersion = Literal['master', 'r4.1.0', 'none']
'C++ driver refs that are under CI test'
SnappyOption = Literal['false', 'true']
"""Should we enable Snappy compression in this build?"""

# A separator character, since we cannot use whitespace
_SEPARATOR = '\N{NO-BREAK SPACE}\N{BULLET}\N{NO-BREAK SPACE}'


def os_split(env: EnvKey) -> tuple[str, None | str]:
def os_split(env: EnvImage) -> tuple[str, None | str]:
"""Convert the environment key into a pretty name+version pair"""
match env:
# Match 'alpine3.18' 'alpine53.123' etc.
case alp if mat := re.match(r'alpine(\d+\.\d+)', alp):
# Match 'alpine:3.18' 'alpine:53.123' etc.
case alp if mat := re.match(r'alpine:(\d+\.\d+)', alp):
return ('Alpine', mat[1])
case 'archlinux':
return 'ArchLinux', None
# Match 'u22', 'u20', 'u71' etc.
case ubu if mat := re.match(r'u(\d\d)', ubu):
return 'Ubuntu', f'{mat[1]}.04'
# Match 'centos9', 'centos10', etc.
case cent if mat := re.match(r'centos(\d+)', cent):
# Match 'ubuntu:<version>'.
case ubu if mat := re.match(r'ubuntu:(\d\d.*)', ubu):
return 'Ubuntu', f'{mat[1]}'
# Match 'centos:9', 'centos:stream10', etc.
case cent if mat := re.match(r'.*centos:(?:stream)?(\d+)', cent):
return 'CentOS', f'{mat[1]}'
# Match 'almalinux8', 'almalinux10', etc.
case alm if mat := re.match(r'almalinux(\d+)', alm):
# Match 'almalinux:8', 'almalinux:10', etc.
case alm if mat := re.match(r'almalinux:(\d+.*)', alm):
return 'AlmaLinux', f'{mat[1]}'
case _:
raise ValueError(f'Failed to split OS env key {env=} into a name+version pair (unrecognized)')


def from_container_image(img: EnvImage) -> str:
"""
Modify an unqualified FROM container identifier to route to our ECR host

NOTE: This will be potentially unnecessary pending the completion of DEVPROD-21478
"""
if '/' in img or img.startswith('+'):
return img
return f'{_ECR_HOST}/dockerhub/library/{img}'


class EarthlyVariant(NamedTuple):
"""
Define a "variant" that runs under a set of Earthly parameters. These are
turned into real EVG variants later on. The Earthly arguments are passed via
expansion parameters.
"""

env: EnvKey
c_compiler: CompilerName
from_: EnvImage
compiler: CompilerName

@property
def display_name(self) -> str:
"""The pretty name for this variant"""
base: str
match os_split(self.env):
match os_split(self.from_):
case name, None:
base = name
case name, version:
base = f'{name} {version}'
toolchain: str
match self.c_compiler:
match self.compiler:
case 'clang':
toolchain = 'LLVM/Clang'
case 'gcc':
Expand All @@ -110,7 +124,7 @@ def task_selector_tag(self) -> str:
The task tag that is used to select the tasks that want to run on this
variant.
"""
return f'{self.env}-{self.c_compiler}'
return f'{self.from_}-{self.compiler}'

@property
def expansions(self) -> Mapping[str, str]:
Expand All @@ -119,8 +133,8 @@ def expansions(self) -> Mapping[str, str]:
from this object.
"""
return {
_CC_PARAM_NAME: self.c_compiler,
_ENV_PARAM_NAME: self.env,
_CC_PARAM_NAME: self.compiler,
_ENV_PARAM_NAME: from_container_image(self.from_),
}

def as_evg_variant(self) -> BuildVariant:
Expand All @@ -145,6 +159,7 @@ class Configuration(NamedTuple):
sasl: SASLOption
tls: TLSOption
test_mongocxx_ref: CxxVersion
snappy: SnappyOption

@property
def suffix(self) -> str:
Expand All @@ -169,7 +184,7 @@ class DockerLoginAmazonECR(Function):
],
args=[
'-c',
'aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 901841024863.dkr.ecr.us-east-1.amazonaws.com',
f'aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin {_ECR_HOST}',
],
),
]
Expand Down Expand Up @@ -206,11 +221,11 @@ def earthly_exec(
'./tools/earthly.sh',
args=[
# Use Amazon ECR as pull-through cache for DockerHub to avoid rate limits.
'--buildkit-image=901841024863.dkr.ecr.us-east-1.amazonaws.com/dockerhub/earthly/buildkitd:v0.8.3',
f'--buildkit-image={_ECR_HOST}/dockerhub/earthly/buildkitd:v0.8.3',
*(f'--secret={k}' for k in (secrets or ())),
f'+{target}',
# Use Amazon ECR as pull-through cache for DockerHub to avoid rate limits.
'--default_search_registry=901841024863.dkr.ecr.us-east-1.amazonaws.com/dockerhub',
f'--default_search_registry={_ECR_HOST}/dockerhub/library',
*(f'--{arg}={val}' for arg, val in (args or {}).items()),
],
command_type=EvgCommandType(kind),
Expand Down Expand Up @@ -243,20 +258,27 @@ def earthly_task(
earthly_args = config._asdict()
earthly_args |= {
# Add arguments that come from parameter expansions defined in the build variant
'env': f'${{{_ENV_PARAM_NAME}}}',
'c_compiler': f'${{{_CC_PARAM_NAME}}}',
'from': f'${{{_ENV_PARAM_NAME}}}',
'compiler': f'${{{_CC_PARAM_NAME}}}',
# Always include a C++ compiler in the build environment for better test coverage
'with_cxx': 'true',
}
return EvgTask(
name=name,
commands=[
DockerLoginAmazonECR.call(),
# First, just build the "env-warmup" which will prepare the build environment.
# First, just build the "build-environment" which will prepare the build environment.
# This won't generate any output, but allows EVG to track it as a separate build step
# for timing and logging purposes. The subequent build step will cache-hit the
# warmed-up build environments.
earthly_exec(
kind='setup',
target='env-warmup',
target='build-environment',
args=earthly_args,
),
earthly_exec(
kind='setup',
target='configure',
args=earthly_args,
),
# Now execute the main tasks:
Expand All @@ -274,7 +296,7 @@ def earthly_task(

CONTAINER_RUN_DISTROS = [
'amazon2',
"debian11-latest-large",
'debian11-latest-large',
'debian12-latest-large',
'ubuntu2204-large',
'ubuntu2404-large',
Expand Down
Loading