Allow an environment to define only onExit - #338
Conversation
An environment script that defined onExit without onEnter was rejected at template decode with "onEnter is required." This blocked cleanup-only environments, including queue environments whose only work is tearing down state established elsewhere. Restore the one-of rule this validator applied before the strict check was added: an ordinary environment script must define onEnter or onExit, and either action alone is sufficient. An actions object that defines neither is still rejected, and the WRAP_ACTIONS extension gating, the all-or-nothing wrap-hook rule, and the wrapped-variable scope rules are unchanged. The removed check was also the only reason the validator inspected the parsing context on the ordinary-action path, so the behavior no longer differs between template decode and job instantiation. Signed-off-by: David Leong <116610336+leongdl@users.noreply.github.com>
| pytest.param(["EXPR", "WRAP_ACTIONS"], id="EXPR and WRAP_ACTIONS"), | ||
| ), | ||
| ) | ||
| def test_parse_onexit_only(self, supported_extensions: list[str]) -> None: |
There was a problem hiding this comment.
This relaxation is only covered on the pure-Python (v0) side. AGENTS.md ("Reference parity") asks that every reference test under test/openjd/model_v0/ have an equivalent under test/openjd/model_v1/ exercising the same behaviour through the Rust binding, and there is currently no v1 test that decodes an environment whose script.actions defines onExit only — the closest fixture (MINIMAL_ENV in test_rust_model_bindings.py:36) defines both actions.
That matters more than usual here because the constraint being removed was introduced in a2cc32f as part of the openjd-rs parity work. If openjd-model 0.5.2 still rejects onExit-only, this change flips the divergence rather than closing it: v0 would accept a template that decode_environment_template through the binding rejects, and nothing in the suite would catch it.
Suggest adding a v1 counterpart that decodes {"actions": {"onExit": {"command": "foo"}}} — if it passes, it is a regression test for the parity you are asserting; if it fails, it belongs in test/openjd/model_v1/test_known_gaps.py as an xfail so the gap is recorded.
Fixes:
What was the problem/requirement? (What/Why)
An environment script that defines
onExitwithoutonEnteris rejected at template decode:This blocks cleanup-only environments. The motivating case is a queue environment whose only work is tearing down state established elsewhere in the session, but the same environment type is used by
jobEnvironmentsand step environments, so all three are affected.The rejection comes from a check added in #318 as a validation tightening. Before that change this validator only required that one of the two ordinary actions be present:
What was the solution? (How)
Remove the added
onEnter is required.branch and restore the one-of rule. An ordinary environment script must defineonEnteroronExit; either action alone is sufficient.Unchanged:
actionsobject defining neither ordinary action is still rejected withMust define one of: onEnter or onExitWRAP_ACTIONSextension gating, theEXPRprerequisite, and the all-or-nothing wrap-hook ruleThe removed check was also the only reason the ordinary-action path inspected the parsing context, so validation no longer differs between template decode and job instantiation.
What is the impact of this change?
Templates that were previously rejected are now accepted. Nothing that was accepted becomes rejected.
actionsonEnteronlyonEnterandonExitonExitonlyCross-implementation note:
openjd-rsstill rejectsonExit-only, so this change makes the two implementations disagree until the same change lands there. The corresponding conformance case is proposed in openjd-specifications.How was this change tested?
hatch run test— 5483 passed, 24 skipped, 3 xfailed, coverage 94%hatch run lint— ruff, black, and mypy cleanhatch build— sdist and wheel builtonExit-only fixtures that assert rejection and are updated in the companion openjd-specifications change.New tests:
test_action.py—onExit-only accepted both with no extensions and withEXPR/WRAP_ACTIONS, asserting the decoded actions; emptyactionsstill rejected, asserted on the full error messagetest_environment_template.py— a standaloneenvironment-2023-09template whose script defines onlyonExittest_job_template.py— ajobEnvironmentsentry whose script defines onlyonExitHave you run the unit tests? Yes.
Was this change documented?
Is this a breaking change?
No. The change only widens what is accepted.
Does this change impact security?
No. No files, directories, permissions, or process boundaries are affected.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.