forked from canonical/snapcraft
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: validate appstream metadata links and prefer links from project …
…metadata (canonical#4888) - Validate that update_contact, donation, vcs-browser, bugtracker, and homepage fields adopted from an appstream metadata file are valid URLs or email addresses. - Contact, donation, source-code, issues, and website fields in a snapcraft.yaml take priority over appstream metadata
- Loading branch information
1 parent
4f3c19d
commit fad8df3
Showing
7 changed files
with
154 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,22 +50,40 @@ class TestAppstreamData: | |
("id", {}, "common_id", "test-id", "test-id"), | ||
("name", {}, "title", "test-title", "test-title"), | ||
("project_license", {}, "license", "test-license", "test-license"), | ||
("update_contact", {}, "contact", "test-contact", ["test-contact"]), | ||
("url", {"type": "homepage"}, "website", "test-website", ["test-website"]), | ||
("url", {"type": "bugtracker"}, "issues", "test-issues", ["test-issues"]), | ||
( | ||
"update_contact", | ||
{}, | ||
"contact", | ||
"[email protected]", | ||
["[email protected]"], | ||
), | ||
( | ||
"url", | ||
{"type": "homepage"}, | ||
"website", | ||
"http://test-website.test", | ||
["http://test-website.test"], | ||
), | ||
( | ||
"url", | ||
{"type": "bugtracker"}, | ||
"issues", | ||
"http://test-issues.test", | ||
["http://test-issues.test"], | ||
), | ||
( | ||
"url", | ||
{"type": "donation"}, | ||
"donation", | ||
"test-donation", | ||
["test-donation"], | ||
"http://test-donation.test", | ||
["http://test-donation.test"], | ||
), | ||
( | ||
"url", | ||
{"type": "vcs-browser"}, | ||
"source_code", | ||
"test-source", | ||
["test-source"], | ||
"test@test.com", | ||
["test@test.com"], | ||
), | ||
], | ||
) | ||
|
@@ -678,6 +696,7 @@ def test_appstream_links(self): | |
<li xml:lang="es">Publica snaps en la tienda.</li> | ||
</ul> | ||
</description> | ||
<update_contact>https://hello.com</update_contact> | ||
<url type="homepage">https://johnfactotum.github.io/foliate/</url> | ||
<url type="vcs-browser">https://github.com/johnfactotum/foliate</url> | ||
<url type="bugtracker">https://github.com/johnfactotum/foliate/issues</url> | ||
|
@@ -692,6 +711,7 @@ def test_appstream_links(self): | |
metadata = appstream.extract(file_name, workdir=".") | ||
|
||
assert metadata is not None | ||
assert metadata.contact == ["https://hello.com"] | ||
assert metadata.website == ["https://johnfactotum.github.io/foliate/"] | ||
assert metadata.issues == ["https://github.com/johnfactotum/foliate/issues"] | ||
assert metadata.donation == ["https://www.buymeacoffee.com/johnfactotum"] | ||
|
@@ -708,6 +728,7 @@ def test_appstream_url(self): | |
<project_license>GPL-3.0-or-later</project_license> | ||
<content_rating type="oars-1.1"/> | ||
<name>Drawing</name> | ||
<update_contact>[email protected]</update_contact> | ||
<url type="homepage">https://johnfactotum.github.io/foliate/</url> | ||
<url type="vcs-browser">https://github.com/johnfactotum/foliate</url> | ||
</component> | ||
|
@@ -717,6 +738,7 @@ def test_appstream_url(self): | |
|
||
metadata = appstream.extract(file_name, workdir=".") | ||
assert metadata is not None | ||
assert metadata.contact == ["[email protected]"] | ||
assert metadata.source_code == ["https://github.com/johnfactotum/foliate"] | ||
|
||
def test_appstream_with_multiple_lists(self): | ||
|
@@ -749,6 +771,39 @@ def test_appstream_with_multiple_lists(self): | |
assert metadata.website == ["https://johnfactotum.github.io/foliate/"] | ||
assert metadata.donation is None | ||
|
||
def test_appstream_with_malformed_links(self): | ||
file_name = "test.appdata.xml" | ||
content = textwrap.dedent( | ||
"""\ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<component type="desktop"> | ||
<id>com.github.maoschanz.drawing</id> | ||
<metadata_license>CC0-1.0</metadata_license> | ||
<project_license>GPL-3.0-or-later</project_license> | ||
<content_rating type="oars-1.1"/> | ||
<name>Drawing</name> | ||
<url type="homepage">bad_invalid_mail</url> | ||
<url type="homepage">https://hello.com</url> | ||
<url type="vcs-browser">file://invalid.file.link</url> | ||
<url type="vcs-browser">http://missing-dot-com</url> | ||
<url type="bugtracker">https://github.com/alainm23/planify/issues</url> | ||
<url type="bugtracker">https:/missing-slash.com</url> | ||
<url type="donation">https://www.buymeacoffee.com/alainm23</url> | ||
<url type="donation">paypal.me/bad</url> | ||
<update_contact>[email protected]</update_contact> | ||
<update_contact>malformed_invalid@mailcom</update_contact> | ||
</component> | ||
""" | ||
) | ||
Path(file_name).write_text(content) | ||
metadata = appstream.extract(file_name, workdir=".") | ||
assert metadata is not None | ||
assert metadata.contact == ["[email protected]"] | ||
assert metadata.donation == ["https://www.buymeacoffee.com/alainm23"] | ||
assert metadata.website == ["https://hello.com"] | ||
assert metadata.source_code == None | ||
assert metadata.issues == ["https://github.com/alainm23/planify/issues"] | ||
|
||
def test_appstream_parse_error(self): | ||
file_name = "snapcraft_legacy.appdata.xml" | ||
content = textwrap.dedent( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,10 +73,8 @@ def yaml_data(extra_args: Dict[str, Any]): | |
"confinement": "strict", | ||
"license": "license", | ||
"contact": "contact1", | ||
"donation": "donation1", | ||
"issues": "issues1", | ||
"website": "website1", | ||
"source-code": "source-code", | ||
"parts": {}, | ||
**extra_args, | ||
} | ||
|
@@ -133,11 +131,11 @@ def test_update_project_metadata(project_yaml_data, appstream_file, new_dir): | |
assert project.summary == "summary" # already set in project | ||
assert project.description == "description" # already set in project | ||
assert project.version == "0.1" # already set in project | ||
assert project.contact == ["contact1", "contact2"] | ||
assert project.issues == ["issues1", "issues2"] | ||
assert project.donation == ["donation1", "donation2"] | ||
assert project.website == ["website1", "website2"] | ||
assert project.source_code == ["source-code", "vcs-browser"] # adopts from project | ||
assert project.contact == ["contact1"] # already set in project | ||
assert project.issues == ["issues1"] # already set in project | ||
assert project.donation == ["donation2"] | ||
assert project.website == ["website1"] # already set in project | ||
assert project.source_code == ["vcs-browser"] | ||
assert project.icon == "assets/icon.png" | ||
assert project.apps["app3"].desktop == "assets/file.desktop" | ||
|
||
|
@@ -256,6 +254,7 @@ def test_update_project_metadata_multiple( | |
metadata2 = ExtractedMetadata( | ||
summary="metadata summary", | ||
description="metadata description", | ||
contact=["contact1"], | ||
website=["website1"], | ||
source_code=["source-code"], | ||
issues=["issues1", "issues3"], | ||
|
@@ -267,7 +266,7 @@ def test_update_project_metadata_multiple( | |
metadata4 = ExtractedMetadata( | ||
summary="extra summary", description="extra description" | ||
) | ||
metadata5 = ExtractedMetadata(license="GPL-3.0", contact=["[email protected]"]) | ||
metadata5 = ExtractedMetadata(license="GPL-3.0", contact=["contact2", "contact1"]) | ||
metadata6 = ExtractedMetadata( | ||
source_code=["source-code", "vcs-browser"], | ||
website=["website2"], | ||
|
@@ -296,14 +295,55 @@ def test_update_project_metadata_multiple( | |
assert project.description == expected["description"] | ||
assert project.title == expected["title"] | ||
assert project.grade == expected["grade"] | ||
assert project.contact == ["[email protected]"] | ||
assert project.contact == ["contact1", "contact2"] | ||
assert project.license == "GPL-3.0" | ||
assert project.donation == ["donation1", "donation2"] | ||
assert project.source_code == ["source-code", "vcs-browser"] | ||
assert project.issues == ["issues1", "issues3", "issues2"] | ||
assert project.website == ["website1", "website2"] | ||
|
||
|
||
def test_update_project_metadata_overriding_appstream(new_dir): | ||
yaml_data = { | ||
"name": "my-project", | ||
"base": "core22", | ||
"confinement": "strict", | ||
"adopt-info": "part", | ||
"parts": {}, | ||
"contact": "[email protected]", | ||
"donation": "https://paypal.me/", | ||
"issues": "https://test.com/issues", | ||
"source-code": "https://test.com/source-code", | ||
"website": "https://test.com/website", | ||
} | ||
project = Project(**yaml_data) | ||
metadata = ExtractedMetadata( | ||
version="4.5.6", | ||
summary="metadata summary", | ||
description="metadata description", | ||
contact=["[email protected]"], | ||
website=["https://example.com/website"], | ||
source_code=["https://example.com/source-code"], | ||
issues=["https://example.com/issues", "https://example.com/issues2"], | ||
donation=["https://buyme.coffee", "https://github.com/sponsors"], | ||
) | ||
prj_vars = {"version": "", "grade": ""} | ||
update_project_metadata( | ||
project, | ||
project_vars=prj_vars, | ||
metadata_list=[metadata], | ||
assets_dir=new_dir, | ||
prime_dir=new_dir, | ||
) | ||
|
||
assert project is not None | ||
assert project.contact == ["[email protected]"] | ||
assert project.donation == ["https://paypal.me/"] | ||
assert project.issues == ["https://test.com/issues"] | ||
assert project.source_code == ["https://test.com/source-code"] | ||
assert project.website == ["https://test.com/website"] | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"project_entries,icon_exists,asset_exists,expected_icon", | ||
[ | ||
|