Skip to content

Refactor Earthly EVG tasks for better consistency with C Driver tasks #1525

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 0 additions & 4 deletions .evergreen/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ pre_error_fails_task: true
# teardown_group commands of appropriate task groups.
post_error_fails_task: false

# Unlikely, but document loudly when task failure is due to early termination.
early_termination:
- func: early-termination

# TODO: move into timeout commands of appropriate task groups.
timeout:
- func: backtrace
Expand Down
22 changes: 0 additions & 22 deletions .evergreen/config_generator/components/early_termination.py

This file was deleted.

94 changes: 37 additions & 57 deletions .evergreen/config_generator/components/earthly.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,29 @@
from typing import Any, Iterable, Literal, TypeVar, get_args, NamedTuple, get_type_hints
from shrub.v3.evg_build_variant import BuildVariant
from shrub.v3.evg_task import EvgTaskRef
from ..etc.utils import Task
from shrub.v3.evg_command import subprocess_exec, EvgCommandType

T = TypeVar("T")
from config_generator.etc.utils import Task

_ENV_PARAM_NAME = "MONGOC_EARTHLY_ENV"
"The name of the EVG expansion parameter used to key the Earthly build env"
T = TypeVar("T")

EnvKey = Literal["u22", "alpine3.18", "archlinux"]
"Identifiers for environments. These correspond to special '*-env' targets in the Earthfile."
# Identifiers for environments. These correspond to special '*-env' targets in the Earthfile.
EnvKey = Literal["ubuntu2204", "alpine3.19", "archlinux"]

# A mapping from environment keys to 'pretty' environment names.
_ENV_NAMES: dict[EnvKey, str] = {
"u22": "Ubuntu 22.04",
"alpine3.18": "Alpine 3.18",
"ubuntu2204": "Ubuntu 22.04",
"alpine3.19": "Alpine 3.19",
"archlinux": "Arch Linux",
}
"A mapping from environment keys to 'pretty' environment names"

# Other options: SSPI (Windows only), AUTO (not reliably test-able without more environments)
SASLOption = Literal["Cyrus", "off"]
"Valid options for the SASL configuration parameter"
TLSOption = Literal["LibreSSL", "OpenSSL", "off"]
"Options for the TLS backend configuration parameter (AKA 'ENABLE_SSL')"
# Other options.
# Valid options for the SASL configuration parameter.
SASLOption = Literal["cyrus", "off"]
# Options for the TLS backend configuration parameter (aka 'ENABLE_SSL').
TLSOption = Literal["libressl", "openssl", "off"]
# C++ Driver versions that are under CI test.
CxxVersion = Literal["master", "r3.8.0"]
"C++ driver refs that are under CI test"

# A Unicode non-breaking space character
_BULLET = "\N{Bullet}"


class Configuration(NamedTuple):
Expand All @@ -49,7 +44,7 @@ class Configuration(NamedTuple):

sasl: SASLOption
tls: TLSOption
test_mongocxx_ref: CxxVersion
version: CxxVersion

@classmethod
def all(cls) -> Iterable[Configuration]:
Expand All @@ -73,7 +68,7 @@ def all(cls) -> Iterable[Configuration]:

@property
def suffix(self) -> str:
return f"{_BULLET}".join(f"{k}={v}" for k, v in self._asdict().items())
return "-".join(f"{k}-{v}" for k, v in self._asdict().items())


def task_filter(env: EnvKey, conf: Configuration) -> bool:
Expand All @@ -83,15 +78,15 @@ def task_filter(env: EnvKey, conf: Configuration) -> bool:
"""
match env, conf:
# We only need one task with "sasl=off"
case "u22", ("off", "OpenSSL", "master"):
case "ubuntu2204", ("off", "openssl", "master"):
return True
# Other sasl=off tasks we'll just ignore:
case _, ("off", _tls, _cxx):
return False
# Ubuntu does not ship with a LibreSSL package:
case e, (_sasl, "LibreSSL", _cxx) if _ENV_NAMES[e].startswith("Ubuntu"):
case e, (_sasl, "libressl", _cxx) if e.startswith("ubuntu"):
return False
# Anything else: Allow it to run:
# Run all other combinations.
case _:
return True

Expand All @@ -108,17 +103,11 @@ def earthly_task(
name: str,
targets: Iterable[str],
config: Configuration,
env: EnvKey,
) -> Task | None:
# Attach "earthly-xyz" tags to the task to allow build variants to select
# these tasks by the environment of that variant.
env_tags = sorted(f"earthly-{e}" for e in sorted(envs_for(config)))
if not env_tags:
# All environments have been excluded for this configuration. This means
# the task itself should not be run:
return
# Generate the build-arg arguments based on the configuration options. The
# NamedTuple field names must match with the ARG keys in the Earthfile!
earthly_args = [f"--{key}={val}" for key, val in config._asdict().items()]
earthly_args = " ".join(f"--{key}={val}" for key, val in config._asdict().items())
return Task(
name=name,
commands=[
Expand All @@ -129,10 +118,8 @@ def earthly_task(
subprocess_exec(
"bash",
args=[
"tools/earthly.sh",
"+env-warmup",
f"--env=${{{_ENV_PARAM_NAME}}}",
*earthly_args,
"-c",
f"./tools/earthly.sh +env-warmup --env={env} {earthly_args}",
],
working_dir="mongoc",
command_type=EvgCommandType.SETUP,
Expand All @@ -141,18 +128,14 @@ def earthly_task(
subprocess_exec(
"bash",
args=[
"tools/earthly.sh",
"+run",
f"--targets={' '.join(targets)}",
f"--env=${{{_ENV_PARAM_NAME}}}",
*earthly_args,
"-c",
f"./tools/earthly.sh +run --targets=\"{' '.join(targets)}\" --env={env} {earthly_args}",
],
working_dir="mongoc",
command_type=EvgCommandType.TEST,
),
],
tags=[f"earthly", "pr-merge-gate", *env_tags],
run_on=CONTAINER_RUN_DISTROS,
tags=["earthly", "pr-merge-gate", f"earthly-{env}"],
)


Expand All @@ -171,25 +154,22 @@ def earthly_task(

def tasks() -> Iterable[Task]:
for conf in Configuration.all():
task = earthly_task(
name=f"check:{conf.suffix}",
targets=("test-example", "test-cxx-driver"),
config=conf,
)
if task is not None:
yield task
for env in envs_for(conf):
yield earthly_task(
name=f"earthly-{env}-{conf.suffix}",
targets=("test-example", "test-cxx-driver"),
config=conf,
env=env,
)


def variants() -> list[BuildVariant]:
envs: tuple[EnvKey, ...] = get_args(EnvKey)
return [
BuildVariant(
name=f"earthly-{env}",
tasks=[EvgTaskRef(name=f".earthly-{env}")],
display_name=_ENV_NAMES[env],
expansions={
_ENV_PARAM_NAME: env,
},
name="earthly",
tasks=[EvgTaskRef(name=".earthly")],
display_name="earthly",
# Earthly tasks do not depend on a specific EVG distro.
run_on=CONTAINER_RUN_DISTROS,
)
for env in envs
]
9 changes: 0 additions & 9 deletions .evergreen/generated_configs/functions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,6 @@ functions:
args:
- -c
- EXTRA_CONFIGURE_FLAGS="-DENABLE_PIC=ON ${EXTRA_CONFIGURE_FLAGS}" .evergreen/scripts/compile.sh
early-termination:
- command: subprocess.exec
params:
binary: bash
args:
- -c
- |
echo 'EVERGREEN HOST WAS UNEXPECTEDLY TERMINATED!!!' 1>&2
echo 'Restart this Evergreen task and try again!' 1>&2
fetch-build:
- command: subprocess.exec
type: setup
Expand Down
Loading