diff --git a/CHANGELOG.md b/CHANGELOG.md
index a29d5a0..291c491 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,16 @@ See the fragment files in the [changelog.d/ directory](./changelog.d).
+
+## 21.2.1 — 2026-05-28
+
+### Fixed
+
+- Properly mirror the LMS caddy block in the default catch-all block used by `DRYDOCK_ENABLE_MULTITENANCY`.
+
+- Avoid retriggering the CONFIG_LOADED action multiple times when redering the
+ jobs templates.
+
## 21.2.0 — 2026-04-24
diff --git a/changelog.d/20260525_165246_deimer.morales_refactor_extra_lms_rules.md b/changelog.d/20260525_165246_deimer.morales_refactor_extra_lms_rules.md
deleted file mode 100644
index e4ae25a..0000000
--- a/changelog.d/20260525_165246_deimer.morales_refactor_extra_lms_rules.md
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-### Fixed
-
-- Properly mirror the LMS caddy block in the default catch-all block used by `DRYDOCK_ENABLE_MULTITENANCY`.
-
-
diff --git a/drydock/plugin.py b/drydock/plugin.py
index a8bda9c..357e3f2 100644
--- a/drydock/plugin.py
+++ b/drydock/plugin.py
@@ -5,7 +5,6 @@
from glob import glob
import click
-from tutor import config as tutor_config
from tutor import env as tutor_env
from tutor import hooks as tutor_hooks
from tutor import serialize, types
@@ -17,6 +16,8 @@
INIT_JOBS_SYNC_WAVE = 1
+TUTOR_CONFIG: types.Config = {}
+
tutor_hooks.Filters.CONFIG_DEFAULTS.add_items(
[
("DRYDOCK_VERSION", __version__),
@@ -59,6 +60,12 @@
)
+@tutor_hooks.Actions.CONFIG_LOADED.add()
+def _capture_config(config: types.Config) -> None:
+ global TUTOR_CONFIG
+ TUTOR_CONFIG = config
+
+
# This function is taken from
# https://github.com/overhangio/tutor/blob/v16.1.8/tutor/commands/k8s.py#L182
def _load_jobs(tutor_conf: types.Config) -> t.Iterable[t.Any]:
@@ -73,21 +80,21 @@ def _load_jobs(tutor_conf: types.Config) -> t.Iterable[t.Any]:
# and https://github.com/overhangio/tutor/blob/v16.1.8/tutor/commands/k8s.py#L82
def get_init_tasks():
"""Return the list of init tasks to run."""
+ if not TUTOR_CONFIG:
+ return []
init_tasks = list(tutor_hooks.Filters.CLI_DO_INIT_TASKS.iterate())
- context = click.get_current_context().obj
- tutor_conf = tutor_config.load(context.root)
- jobs = tutor_conf.get("DRYDOCK_INIT_JOBS_EXCLUDED", [])
+ jobs = TUTOR_CONFIG.get("DRYDOCK_INIT_JOBS_EXCLUDED", [])
if not isinstance(jobs, list):
click.secho("'DRYDOCK_INIT_JOBS_EXCLUDED' must be a list. Ignoring.", fg="yellow")
jobs = []
excluded_init_jobs = set(jobs)
for i, (service, command) in enumerate(init_tasks):
- for template in _load_jobs(tutor_conf):
+ for template in _load_jobs(TUTOR_CONFIG):
if template["metadata"]["name"] != service + "-job" or template["metadata"]["name"] in excluded_init_jobs:
continue
- render_command = tutor_env.render_str(tutor_conf, command)
+ render_command = tutor_env.render_str(TUTOR_CONFIG, command)
template["metadata"]["name"] = "drydock-" + template["metadata"]["name"] + "-" + str(i)
template["metadata"]["labels"].update(
diff --git a/pyproject.toml b/pyproject.toml
index c84d12a..611e27c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "tutor-contrib-drydock"
-version = "21.2.0"
+version = "21.2.1"
description = "A Tutor plugin to manage our opinionated Open edX operations"
readme = "README.md"
requires-python = ">=3.10"
diff --git a/uv.lock b/uv.lock
index ee9e106..baac1b7 100644
--- a/uv.lock
+++ b/uv.lock
@@ -833,7 +833,7 @@ sdist = { url = "https://files.pythonhosted.org/packages/26/d8/3d93bc551ba2e5035
[[package]]
name = "tutor-contrib-drydock"
-version = "21.2.0"
+version = "21.2.1"
source = { editable = "." }
dependencies = [
{ name = "tutor" },