diff --git a/terraform/bootstrap/stub/handler.py b/terraform/bootstrap/stub/handler.py index bd91b91..6ffe619 100644 --- a/terraform/bootstrap/stub/handler.py +++ b/terraform/bootstrap/stub/handler.py @@ -1,4 +1,8 @@ -"""Bootstrap stub. GitHub Actions replaces this zip via update-function-code.""" +"""Bootstrap stub. GitHub Actions replaces this zip via update-function-code. + +Keep a module for every Lambda handler setting in locals.functions. A recreate +must return 503 instead of failing at init because the entrypoint is missing. +""" def handler(event, context): diff --git a/terraform/bootstrap/stub/interactions.py b/terraform/bootstrap/stub/interactions.py new file mode 100644 index 0000000..fea9e2a --- /dev/null +++ b/terraform/bootstrap/stub/interactions.py @@ -0,0 +1,5 @@ +"""Alias so slack_interactions (interactions.handler) can load the stub zip.""" + +from handler import handler + +__all__ = ["handler"] diff --git a/tests/test_bootstrap_stub.py b/tests/test_bootstrap_stub.py new file mode 100644 index 0000000..528d56c --- /dev/null +++ b/tests/test_bootstrap_stub.py @@ -0,0 +1,34 @@ +"""Stub zip must expose every Lambda handler name in locals.functions.""" + +from __future__ import annotations + +import importlib.util +import sys +from pathlib import Path + +STUB_DIR = Path(__file__).resolve().parents[1] / "terraform" / "bootstrap" / "stub" + + +def _load_file(module_name: str, path: Path): + spec = importlib.util.spec_from_file_location(module_name, path) + assert spec is not None and spec.loader is not None + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def test_stub_handler_modules_return_503() -> None: + handler_mod = _load_file("apm_stub_handler", STUB_DIR / "handler.py") + saved_handler = sys.modules.get("handler") + sys.modules["handler"] = handler_mod + try: + interactions_mod = _load_file("apm_stub_interactions", STUB_DIR / "interactions.py") + for module in (handler_mod, interactions_mod): + result = module.handler({}, None) + assert result["statusCode"] == 503 + assert "NOT_DEPLOYED" in result["body"] + finally: + if saved_handler is None: + sys.modules.pop("handler", None) + else: + sys.modules["handler"] = saved_handler