fix(config): a profile's [apps.<name>] table merges into the app definitions, so an overlay can retune an app and not only the gateway - #9052
Conversation
…nitions, so an overlay can retune an app and not only the gateway merge_from_toml_file and apply_profile handled project, check, storage, the capability sections, dependencies and scripts, and had no branch for apps. A jac.<profile>.toml or jac.local.toml carrying [apps.<name>.scale] was read and discarded, while [scale.gateway] three lines below it in the same file was applied, because scale is a capability section and gets deep-merged. reference/apps.md documents the profile as layer 3 and the app overlay as layer 2 with later layers winning, so the profile's table should override the base one. Both paths now deep-merge the overlay's [apps] table onto _base_data's and re-parse through parse_apps, so the merged table gets the same validation the base one does (unknown keys, kinds, route collisions) and config.apps stays derived from one table rather than from two merge implementations. An overlay that declares [apps] against a non-workspace jac.toml is rejected rather than silently starting a workspace.
christianwilkins
left a comment
There was a problem hiding this comment.
Reviewed 9f5980cc27bd82daec3fc747658f301b9b54cdc7, including the full diff, both profile merge paths, app parsing/validation, and effective per-app configuration. No blocking findings.
Independent macOS validation using this checkout's compiler source: all 27 tests in jac/jaclang/scale/tests/apps passed. Two additional probes also passed: inherited [environments] app settings retain base fields, and jac.local.toml app settings take precedence over the selected file profile. git diff --check passes. I did not run a real cluster deployment.
The shared merge helper preserves the existing nested settings and reuses parse_apps validation; re-interpolating the raw base app table also preserves the base route scenario covered by the new regression test. The follow-up 9f5980cc2 commit only adds the release note. No fixes were needed or made during review.
I rechecked the remote head: unchanged, non-draft, and conflict-free. Current-head CI and pre-commit.ci are green, including the Scale deploy and Kubernetes checks. Status: approved and ready to merge from this review.
Closes #8995.
What this changes
merge_from_toml_file(which readsjac.<profile>.tomlandjac.local.toml) andapply_profile(which reads[environments.<name>]) each handleproject,check,storage, the capability sections, dependencies, environments and scripts, and had noappsbranch at all. So a profile's[apps.worker_sv.scale]was parsed and thrown away, while[scale.gateway]three lines below it in the same file was applied, becausescaleis a capability section and gets deep-merged.reference/apps.mddocuments the profile as layer 3 and the app overlay as layer 2, later layers winning, so the profile's table is supposed to override the base one. That asymmetry is what the report describes.Both paths now call one new
JacConfig.merge_apps_table, which deep-merges the overlay's[apps]onto_base_data's and re-parses the result throughparse_apps. Two consequences worth stating, because they are why this is one function rather than two merge sites:kind, absolute paths, route collisions), instead of a second, laxer path intoconfig.apps;config.appsstays derived from one table. Readers needed no change:app_scale_overridesandfleet_from_configboth already resolveconfig.apps[name].overlays.The re-parse runs
_interpolate_recursiveover the merged table beforeparse_apps, mirroring the load path (_parse_toml_datastoresrawin_base_dataand parses the interpolated copy). Without it,_base_databeing the un-interpolated store means a base app's${VAR}would come back literal the moment any overlay declared[apps]- the fix would have introduced that. There is a test for it._deep_mergereplaces lists rather than concatenating them, so an overlay that sets[apps.<n>.scale] exempt_pathsrestates the whole list. That is the existing behaviour for every other section, not new here.Behavior change
An overlay that declares
[apps]against ajac.tomlwith no[apps]table is now rejected:Previously it was silently ignored, which is the same class of silence as the bug itself. A single-app project that had a stray
[apps]injac.local.tomlwill now fail loud instead of quietly not applying it.Tests
One new test each for the two properties, both in
scale/tests/apps/test_app_scale_overrides.jac- the file whose docstring already claims this surface - reusing its_project()helper andreset_scale_configdiscipline. No new file, no mocks: realjac.tomlandjac.e2e.tomlon disk, read through the realJAC_PROFILEpath.Both fail on unmodified main:
and with only the
_interpolate_recursivecall removed and the rest of the fix in place, the second one fails on the half it exists to protect:Validation
Run on a Linux x86_64 dev build from this checkout (
jac dev mode - using compiler source at ~/jaseci-w2/jacconfirmed in each run), rebased onto9b02a4b2d9:jac/tests/project/(ownsJacConfig)jac/jaclang/scale/tests/apps/jac/jaclang/scale/tests/misc/Pre-fix runs: 25 passed / 1 failed / 1 error with both source files reverted, and 26 passed / 1 failed with only the interpolation call removed.
Not run:
jac/jaclang/scale/tests/deploy/, the k8s e2e lanes, and any real cluster deploy. This changes config parsing only and touches no manifest or runtime path, but a deploy that readsconfig.appsunder a profile is the case I did not exercise on a cluster. CI covers the deploy suite.