Repository: canonical/snapcraft

Issue:
Local key assets are not used in package-repositories for core24
### Bug Description

Local key assets are not used in package-repositories for core24 (only the keyserver is supported)

### To Reproduce

.

### Environment

.

### snapcraft.yaml

```shell
.
```


### Relevant log output

```shell
.
```


### Additional context

_No response_


Discussion:

Thank you for reporting us your feedback!

The internal ticket has been created: https://warthogs.atlassian.net/browse/CRAFT-2825.

> This message was autogenerated


Resolving patch:
diff --git a/snapcraft/services/lifecycle.py b/snapcraft/services/lifecycle.py
--- a/snapcraft/services/lifecycle.py
+++ b/snapcraft/services/lifecycle.py
@@ -29,6 +29,7 @@
 from overrides import overrides
 
 from snapcraft import __version__, errors, models, os_release, parts, utils
+from snapcraft.parts.yaml_utils import get_snap_project
 
 
 class Lifecycle(LifecycleService):
@@ -169,6 +170,15 @@ def generate_manifest(self) -> models.Manifest:
             primed_stage_packages=sorted(primed_stage_packages),
         )
 
+    @overrides
+    def _get_local_keys_path(self) -> Path | None:
+        snap_project = get_snap_project()
+        keys_dir = snap_project.assets_dir / "keys"
+        if keys_dir.is_dir():
+            return keys_dir
+
+        return None
+
 
 def get_prime_dirs_from_project(project_info: ProjectInfo) -> dict[str | None, Path]:
     """Get a mapping of component names to prime directories from a ProjectInfo.


Test patch:
diff --git a/tests/spread/core24/package-repositories/test-apt-key-fingerprint/snap/snapcraft.yaml b/tests/spread/core24/package-repositories/test-apt-key-fingerprint/snap/snapcraft.yaml
--- a/tests/spread/core24/package-repositories/test-apt-key-fingerprint/snap/snapcraft.yaml
+++ b/tests/spread/core24/package-repositories/test-apt-key-fingerprint/snap/snapcraft.yaml
@@ -25,3 +25,5 @@ package-repositories:
     suites: [focal]
     key-id: 78E1918602959B9C59103100F1831DDAFC42E99D
     url: http://ppa.launchpad.net/snappy-dev/snapcraft-daily/ubuntu
+    # Set an invalid keyserver here to force the use of the local key
+    key-server: keyserver.invalid.com
diff --git a/tests/unit/services/test_lifecycle.py b/tests/unit/services/test_lifecycle.py
--- a/tests/unit/services/test_lifecycle.py
+++ b/tests/unit/services/test_lifecycle.py
@@ -19,6 +19,7 @@
 import platform
 import shutil
 import sys
+from pathlib import Path
 from unittest import mock
 
 import pytest
@@ -220,3 +221,37 @@ def test_lifecycle_installs_gpg_dirmngr(lifecycle_service, mocker):
     mock_install.assert_called_once_with(
         ["gpg", "dirmngr"], refresh_package_cache=False
     )
+
+
+@pytest.mark.parametrize(
+    ("project_location", "assets_dir", "expected_keys_path"),
+    [
+        # These locations come from yaml_utils._SNAP_PROJECT_FILES
+        # snapcraft.yaml locations where the keys are expected to be in snap/keys
+        ("snapcraft.yaml", "snap", "snap/keys"),
+        ("snap/snapcraft.yaml", "snap", "snap/keys"),
+        (".snapcraft.yaml", "snap", "snap/keys"),
+        # snapcraft.yaml location where the keys are expected to be somewhere else
+        ("build-aux/snap/snapcraft.yaml", "build-aux/snap", "build-aux/snap/keys"),
+    ],
+)
+def test_local_keys_path(
+    new_dir, lifecycle_service, project_location, assets_dir, expected_keys_path
+):
+    """Check that _get_local_keys_path() is correct given the location of snapcraft.yaml."""
+    snap_dir = new_dir / Path(project_location).parent
+    snap_dir.mkdir(exist_ok=True, parents=True)
+
+    # The project file itself doesn't really matter, but must exist
+    project_yaml = snap_dir / "snapcraft.yaml"
+    project_yaml.touch()
+
+    # app = application.create_app()
+    keys_dir = Path(assets_dir) / "keys"
+
+    # If the keys dir doesn't exist the method should return None
+    assert not keys_dir.is_dir()
+    assert lifecycle_service._get_local_keys_path() is None
+
+    keys_dir.mkdir(exist_ok=True, parents=True)
+    assert lifecycle_service._get_local_keys_path() == Path(expected_keys_path)