diff --git a/rockcraft/extensions/extension.py b/rockcraft/extensions/extension.py index 707e453fc..e0972c8d9 100644 --- a/rockcraft/extensions/extension.py +++ b/rockcraft/extensions/extension.py @@ -106,7 +106,10 @@ def validate(self, extension_name: str) -> None: # There is nothing to validate, the extension will set the preferred base. return - base: str = self.yaml_data["base"] + # Use get_project_base() so that build-base takes precedence over base (e.g. when + # base is "bare", build-base carries the effective Ubuntu series used for dispatch). + # Fall back to the raw base field if get_project_base() cannot resolve it. + base: str = get_project_base(self.yaml_data) or self.yaml_data["base"] if self.is_experimental(base) and not os.getenv( "ROCKCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS" diff --git a/tests/unit/extensions/test_expressjs.py b/tests/unit/extensions/test_expressjs.py index fd8e747e6..dfcf4f9e5 100644 --- a/tests/unit/extensions/test_expressjs.py +++ b/tests/unit/extensions/test_expressjs.py @@ -398,6 +398,26 @@ def test_expressjs_invalid_package_json_scripts_error( ) +@pytest.mark.usefixtures("expressjs_extension", "package_json_file") +def test_expressjs_extension_bare_base_with_ubuntu2604_build_base( + tmp_path, monkeypatch, expressjs_input_yaml +): + """base:bare + build-base:ubuntu@26.04 should dispatch to V2 without error.""" + monkeypatch.setenv("ROCKCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS", "1") + expressjs_input_yaml["base"] = "bare" + expressjs_input_yaml["build-base"] = "ubuntu@26.04" + applied = extensions.apply_extensions(tmp_path, expressjs_input_yaml) + assert isinstance( + extensions.ExpressJSFrameworkFactory( + project_root=tmp_path, + yaml_data={"name": "x", "base": "bare", "build-base": "ubuntu@26.04"}, + ), + extensions.ExpressJSFrameworkV2, + ) + assert applied["base"] == "bare" + assert applied["build-base"] == "ubuntu@26.04" + + def test_expressjs_factory_dispatch(tmp_path): factory = extensions.ExpressJSFrameworkFactory diff --git a/tests/unit/extensions/test_extensions.py b/tests/unit/extensions/test_extensions.py index ea7801265..cba058319 100644 --- a/tests/unit/extensions/test_extensions.py +++ b/tests/unit/extensions/test_extensions.py @@ -57,13 +57,15 @@ def test_experimental_no_env(tmp_path, input_yaml): assert str(exc.value) == expected_message -@pytest.mark.parametrize("base", ["ubuntu:20.04", "bare"]) +@pytest.mark.parametrize("base", ["ubuntu:20.04", "ubuntu@20.04", "bare"]) def test_wrong_base(tmp_path, input_yaml, base): input_yaml["extensions"] = [FakeExtension.NAME] input_yaml["base"] = base with pytest.raises(errors.ExtensionError) as exc: extensions.apply_extensions(tmp_path, input_yaml) + # get_project_base() normalizes legacy format so we also do the same here to match the expected message. + base = base.replace(":", "@") expected_message = ( f"Extension '{FakeExtension.NAME}' does not support base: '{base}'" )