Skip to content

Commit

Permalink
meta: write out metadata links (#4275)
Browse files Browse the repository at this point in the history
Signed-off-by: Sergio Schvezov <[email protected]>
  • Loading branch information
sergiusens authored Jul 13, 2023
1 parent 833b0f2 commit de56fe6
Show file tree
Hide file tree
Showing 3 changed files with 210 additions and 1 deletion.
41 changes: 40 additions & 1 deletion snapcraft/meta/snap_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from pydantic_yaml import YamlModel

from snapcraft import errors
from snapcraft.projects import App, Project
from snapcraft.projects import App, Project, UniqueStrList
from snapcraft.utils import get_ld_library_paths, process_version


Expand Down Expand Up @@ -176,6 +176,41 @@ def get_content_dirs(self, installed_path: Path) -> Set[Path]:
return content_dirs


class Links(_SnapMetadataModel):
"""Metadata links used in snaps."""

contact: Optional[UniqueStrList]
donation: Optional[UniqueStrList]
issues: Optional[UniqueStrList]
source_code: Optional[UniqueStrList]
website: Optional[UniqueStrList]

@staticmethod
def _normalize_value(
value: Optional[Union[str, UniqueStrList]]
) -> Optional[List[str]]:
if isinstance(value, str):
value = [value]
return value

@classmethod
def from_project(cls, project: Project) -> "Links":
"""Create Links from a Project."""
return cls(
contact=cls._normalize_value(project.contact),
donation=cls._normalize_value(project.donation),
issues=cls._normalize_value(project.issues),
source_code=cls._normalize_value(project.source_code),
website=cls._normalize_value(project.website),
)

def __bool__(self) -> bool:
"""Return True if any of the Links attributes are set."""
return any(
[self.contact, self.donation, self.issues, self.source_code, self.website]
)


class SnapMetadata(_SnapMetadataModel):
"""The snap.yaml model.
Expand Down Expand Up @@ -210,6 +245,7 @@ class Config:
layout: Optional[Dict[str, Dict[str, str]]]
system_usernames: Optional[Dict[str, Any]]
provenance: Optional[str]
links: Optional[Links]

@classmethod
def unmarshal(cls, data: Dict[str, Any]) -> "SnapMetadata":
Expand Down Expand Up @@ -403,6 +439,8 @@ def write(project: Project, prime_dir: Path, *, arch: str):
# project provided assumes and computed assumes
total_assumes = sorted(project.assumes + list(assumes))

links = Links.from_project(project)

snap_metadata = SnapMetadata(
name=project.name,
title=project.title,
Expand All @@ -425,6 +463,7 @@ def write(project: Project, prime_dir: Path, *, arch: str):
layout=project.layout,
system_usernames=project.system_usernames,
provenance=project.provenance,
links=links if links else None,
)
if project.passthrough:
for name, value in project.passthrough.items():
Expand Down
8 changes: 8 additions & 0 deletions tests/spread/general/metadata-links/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@ environment:
prepare: |
snap install yq
#shellcheck source=tests/spread/tools/snapcraft-yaml.sh
. "$TOOLS_DIR/snapcraft-yaml.sh"
set_base snapcraft.yaml
restore: |
snapcraft clean
rm -rf ./*.snap
#shellcheck source=tests/spread/tools/snapcraft-yaml.sh
. "$TOOLS_DIR/snapcraft-yaml.sh"
restore_yaml snapcraft.yaml
execute: |
# Create a snap to trigger `snap pack`.
snapcraft
Expand Down
162 changes: 162 additions & 0 deletions tests/unit/meta/test_snap_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,111 @@ def test_assumes(simple_project, new_dir):
)


def test_links_scalars(simple_project, new_dir):
snap_yaml.write(
simple_project(
contact="[email protected]",
issues="https://hubhub.com/issues",
donation="https://moneyfornothing.com",
source_code="https://closed.acme.com",
website="https://acme.com",
),
prime_dir=Path(new_dir),
arch="amd64",
)
yaml_file = Path("meta/snap.yaml")
assert yaml_file.is_file()

content = yaml_file.read_text()
assert content == textwrap.dedent(
"""\
name: mytest
version: 1.29.3
summary: Single-line elevator pitch for your amazing snap
description: test-description
architectures:
- amd64
base: core22
apps:
app1:
command: bin/mytest
confinement: strict
grade: stable
environment:
LD_LIBRARY_PATH: ${SNAP_LIBRARY_PATH}${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
PATH: $SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$PATH
links:
contact:
- [email protected]
donation:
- https://moneyfornothing.com
issues:
- https://hubhub.com/issues
source-code:
- https://closed.acme.com
website:
- https://acme.com
"""
)


def test_links_lists(simple_project, new_dir):
snap_yaml.write(
simple_project(
contact=[
"[email protected]",
"[email protected]",
],
issues=[
"https://hubhub.com/issues",
"https://corner.com/issues",
],
donation=["https://moneyfornothing.com", "https://prince.com"],
source_code="https://closed.acme.com",
website="https://acme.com",
),
prime_dir=Path(new_dir),
arch="amd64",
)
yaml_file = Path("meta/snap.yaml")
assert yaml_file.is_file()

content = yaml_file.read_text()
assert content == textwrap.dedent(
"""\
name: mytest
version: 1.29.3
summary: Single-line elevator pitch for your amazing snap
description: test-description
architectures:
- amd64
base: core22
apps:
app1:
command: bin/mytest
confinement: strict
grade: stable
environment:
LD_LIBRARY_PATH: ${SNAP_LIBRARY_PATH}${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
PATH: $SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$PATH
links:
contact:
- [email protected]
- [email protected]
donation:
- https://moneyfornothing.com
- https://prince.com
issues:
- https://hubhub.com/issues
- https://corner.com/issues
source-code:
- https://closed.acme.com
website:
- https://acme.com
"""
)


@pytest.fixture
def complex_project():
snapcraft_yaml = textwrap.dedent(
Expand Down Expand Up @@ -1025,3 +1130,60 @@ def test_architectures_all(simple_project, new_dir):
"${SNAP_LIBRARY_PATH}${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}:"
"$SNAP/lib:$SNAP/usr/lib\n"
) in content


##############
# Test Links #
##############


def test_links_for_scalars(simple_project):
project = simple_project(
contact="[email protected]",
issues="https://hubhub.com/issues",
donation="https://moneyfornothing.com",
source_code="https://closed.acme.com",
website="https://acme.com",
)

links = snap_yaml.Links.from_project(project)

assert links.contact == [project.contact]
assert links.issues == [project.issues]
assert links.donation == [project.donation]
assert links.source_code == [project.source_code]
assert links.website == [project.website]

assert bool(links) is True


def test_links_for_lists(simple_project):
project = simple_project(
contact=[
"[email protected]",
"[email protected]",
],
issues=[
"https://hubhub.com/issues",
"https://corner.com/issues",
],
donation=["https://moneyfornothing.com", "https://prince.com"],
)

links = snap_yaml.Links.from_project(project)

assert links.contact == project.contact
assert links.issues == project.issues
assert links.donation == project.donation
assert links.source_code is None
assert links.website is None

assert bool(links) is True


def test_no_links(simple_project):
project = simple_project()

links = snap_yaml.Links.from_project(project)

assert bool(links) is False

0 comments on commit de56fe6

Please sign in to comment.