Skip to content

Commit

Permalink
config: allow bundle without metadata.yaml
Browse files Browse the repository at this point in the history
  • Loading branch information
syu-w committed Jul 4, 2023
1 parent ed7c955 commit 325b211
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 27 deletions.
45 changes: 26 additions & 19 deletions charmcraft/models/charmcraft.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ class CharmcraftConfig(
metadata_legacy: bool = False

type: str
name: pydantic.StrictStr
summary: pydantic.StrictStr
description: pydantic.StrictStr
name: Optional[pydantic.StrictStr]
summary: Optional[pydantic.StrictStr]
description: Optional[pydantic.StrictStr]
charmhub: CharmhubConfig = CharmhubConfig()
parts: Optional[Dict[str, Any]]
bases: Optional[List[BasesConfiguration]]
Expand Down Expand Up @@ -150,11 +150,27 @@ def validate_charm_type(cls, charm_type):
@pydantic.validator("name", pre=True, always=True)
def validate_name(cls, name, values):
"""Verify charm name is valid with exception when instantiated without YAML."""
if not name:
raise ValueError("value must not be empty")
if values.get("type") == "charm" and not name:
raise ValueError("needs value")

return name

@pydantic.validator("summary", pre=True, always=True)
def validate_summary(cls, summary, values):
"""Verify charm summary is valid with exception when instantiated without YAML."""
if values.get("type") == "charm" and not summary:
raise ValueError("needs value")

return summary

@pydantic.validator("description", pre=True, always=True)
def validate_description(cls, description, values):
"""Verify charm name is valid with exception when instantiated without YAML."""
if values.get("type") == "charm" and not description:
raise ValueError("needs value")

return description

@pydantic.validator("parts", pre=True, always=True)
def validate_special_parts(cls, parts, values):
"""Verify parts type (craft-parts will re-validate the schemas for the plugins)."""
Expand Down Expand Up @@ -313,31 +329,22 @@ def unmarshal(cls, obj: Dict[str, Any], project: Project):
}
)
elif obj.get("type") == "bundle":
# only need name from bundle,
# metadata.yaml will be copied without validation
# bundle may not have metadata.yaml.
# but if it does, it should have name and optional description
# metadata.yaml will be copied without validation if it exists
metadata_legacy = parse_bundle_metadata_yaml(project.dirpath)
return cls.parse_obj(
{
"project": project,
"name": metadata_legacy.name,
"summary": "",
"description": metadata_legacy.description or "",
"description": metadata_legacy.description,
"metadata-legacy": True,
**obj,
}
)
else:
# fallthrough for pydantic to handle
return cls.parse_obj(
{
"project": project,
"name": "invalid-type",
"summary": "",
"description": "",
"metadata-legacy": True,
**obj,
}
)
pass

return cls.parse_obj({"project": project, **obj})
except pydantic.error_wrappers.ValidationError as error:
Expand Down
6 changes: 3 additions & 3 deletions tests/commands/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,9 @@ def test_build_error_without_metadata_yaml(basic_project):
assert str(exc_info.value) == dedent(
"""\
Bad charmcraft.yaml content:
- field 'name' required in top-level configuration
- field 'summary' required in top-level configuration
- field 'description' required in top-level configuration"""
- needs value in field 'name'
- needs value in field 'summary'
- needs value in field 'description'"""
)


Expand Down
8 changes: 3 additions & 5 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def test_load_minimal_metadata_from_charmcraft_yaml_missing_name(
)
)

with pytest.raises(CraftError, match="field 'name' required in top-level configuration"):
with pytest.raises(CraftError, match="needs value in field 'name'"):
load(tmp_path)


Expand Down Expand Up @@ -139,7 +139,7 @@ def test_load_minimal_metadata_from_charmcraft_yaml_missing_summary(
),
)

with pytest.raises(CraftError, match="field 'summary' required in top-level configuration"):
with pytest.raises(CraftError, match="needs value in field 'summary'"):
load(tmp_path)


Expand All @@ -161,9 +161,7 @@ def test_load_minimal_metadata_from_charmcraft_yaml_missing_description(
),
)

with pytest.raises(
CraftError, match="field 'description' required in top-level configuration"
):
with pytest.raises(CraftError, match="needs value in field 'description'"):
load(tmp_path)


Expand Down

0 comments on commit 325b211

Please sign in to comment.