Skip to content

Commit

Permalink
fix: install gpg and dirmngr in core24 builds
Browse files Browse the repository at this point in the history
This commit mimicks the behavior for core22<= builds where gpg and dirmngr
are installed at runtime for projects with package-repositories. The trigger
for this commit is the fact that the environment where Snapcraft builds in
Launchpad do _not_ have the 'dirmngr' package installed.

Unfortunately the strategy of bundling 'gpg' and 'dirmngr' as stage-packages
in Snapcraft's own snap didn't work because gpg has the expected path to the
'dirmngr' executable hardcoded (always trying to call '/usr/bin/dirmngr').

Fixes #4740
  • Loading branch information
tigarmo committed Apr 23, 2024
1 parent 9ba9615 commit 0b888a6
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 0 deletions.
9 changes: 9 additions & 0 deletions snapcraft/services/lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from craft_application import AppMetadata, LifecycleService, ServiceFactory
from craft_application.models import BuildInfo
from craft_parts import ProjectInfo, StepInfo
from craft_parts.packages import Repository as Repo
from overrides import overrides

from snapcraft import __version__, errors, models, os_release, parts, utils
Expand Down Expand Up @@ -60,6 +61,14 @@ def __init__( # noqa: PLR0913 (too many arguments)
def setup(self) -> None:
project = cast(models.Project, self._project)

if project.package_repositories:
# Note: we unfortunately need to handle missing gpg/dirmngr binaries
# ourselves here, as this situation happens in Launchpad (where
# builds are executed destructively).
required_packages = ["gpg", "dirmngr"]
if any(p for p in required_packages if not Repo.is_package_installed(p)):
Repo.install_packages(required_packages, refresh_package_cache=False)

# Have the lifecycle install the base snap, and look into it when
# determining the package cutoff.
self._manager_kwargs.update(
Expand Down
7 changes: 7 additions & 0 deletions tests/spread/core24/package-repositories/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ environment:
SNAP/test_foreign_armhf: test-foreign-armhf
SNAP/test_foreign_i386: test-foreign-i386

prepare: |
# Remove the currently installed "gpg" and "dirmngr" packages to ensure that
# Snapcraft itself is installing them when necessary.
sudo dpkg --remove --force-depends gpg dirmngr
restore: |
sudo apt install -y gpg dirmngr
cd "$SNAP"
rm -f ./*.snap
snapcraft clean
Expand Down
22 changes: 22 additions & 0 deletions tests/unit/services/test_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import pytest
import pytest_subprocess
from craft_parts.packages import Repository

from snapcraft import __version__, models, os_release, utils

Expand Down Expand Up @@ -198,3 +199,24 @@ def test_lifecycle_prime_dirs(lifecycle_service):
lifecycle_service.setup()

assert lifecycle_service.prime_dirs == {None: lifecycle_service._work_dir / "prime"}


@pytest.fixture()
def package_repositories_params(extra_project_params):
"""Add package-repositories configuration to the default project."""
extra_project_params["package_repositories"] = [{"type": "apt", "ppa": "test/ppa"}]


@pytest.mark.usefixtures("package_repositories_params", "default_project")
def test_lifecycle_installs_gpg_dirmngr(lifecycle_service, mocker):
mock_is_installed = mocker.patch.object(
Repository, "is_package_installed", return_value=False
)
mock_install = mocker.patch.object(Repository, "install_packages")

lifecycle_service.setup()

assert mock_is_installed.called
mock_install.assert_called_once_with(
["gpg", "dirmngr"], refresh_package_cache=False
)

0 comments on commit 0b888a6

Please sign in to comment.