diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 2b02e5fbc1..5ee3294372 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -14,6 +14,10 @@ build: python: "3.10" apt_packages: - libapt-pkg-dev + jobs: + post_checkout: + - git fetch --tags --depth 1 # Also fetch tags + - git describe # Useful for debugging # Build documentation in the docs/ directory with Sphinx sphinx: diff --git a/docs/reference/plugins.rst b/docs/reference/plugins.rst index a59da7b05b..d00ecde67c 100644 --- a/docs/reference/plugins.rst +++ b/docs/reference/plugins.rst @@ -22,5 +22,6 @@ Snapcraft. /common/craft-parts/reference/plugins/nil_plugin /common/craft-parts/reference/plugins/npm_plugin plugins/python_plugin + /common/craft-parts/reference/plugins/qmake_plugin /common/craft-parts/reference/plugins/rust_plugin /common/craft-parts/reference/plugins/scons_plugin diff --git a/docs/requirements.txt b/docs/requirements.txt index 6f30edf70e..b79468eea7 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -17,7 +17,7 @@ craft-application==2.8.0 craft-archives==1.1.3 craft-cli==2.5.1 craft-grammar==1.2.0 -craft-parts==1.31.0 +craft-parts==1.32.0 craft-providers==1.23.1 craft-store==2.6.2 cryptography==42.0.5 diff --git a/requirements-devel.txt b/requirements-devel.txt index 3d94928913..b4844a7a2e 100644 --- a/requirements-devel.txt +++ b/requirements-devel.txt @@ -15,7 +15,7 @@ craft-application==2.8.0 craft-archives==1.1.3 craft-cli==2.5.1 craft-grammar==1.2.0 -craft-parts==1.31.0 +craft-parts==1.32.0 craft-providers==1.23.1 craft-store==2.6.2 cryptography==42.0.5 diff --git a/requirements.txt b/requirements.txt index 46271d0fd0..205dc942c7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ craft-application==2.8.0 craft-archives==1.1.3 craft-cli==2.5.1 craft-grammar==1.2.0 -craft-parts==1.31.0 +craft-parts==1.32.0 craft-providers==1.23.1 craft-store==2.6.2 cryptography==42.0.5 diff --git a/setup.cfg b/setup.cfg index 64e009835c..2bf3db8942 100644 --- a/setup.cfg +++ b/setup.cfg @@ -39,4 +39,4 @@ ignore = E203,E501 # D203 1 blank line required before class docstring (reason: pep257 default) # D213 Multi-line docstring summary should start at the second line (reason: pep257 default) ignore = D107, D203, D213 -ignore_decorators = overrides +ignore_decorators = override diff --git a/setup.py b/setup.py index c2e9ec633c..450e89f6bd 100755 --- a/setup.py +++ b/setup.py @@ -97,7 +97,7 @@ def recursive_data_files(directory, install_directory): "craft-archives", "craft-cli", "craft-grammar", - "craft-parts", + "craft-parts>=1.32.0", "craft-providers", "craft-store", "docutils<0.20", # Frozen until we can update sphinx dependencies. diff --git a/snapcraft/application.py b/snapcraft/application.py index 6c4cc400ce..d5bc2754ed 100644 --- a/snapcraft/application.py +++ b/snapcraft/application.py @@ -27,6 +27,7 @@ import craft_application.commands as craft_app_commands import craft_cli import craft_parts +import craft_store from craft_application import Application, AppMetadata, util from craft_cli import emit from craft_parts.plugins.plugins import PluginType @@ -34,7 +35,7 @@ import snapcraft import snapcraft_legacy -from snapcraft import cli, errors, models, services +from snapcraft import cli, errors, models, services, store from snapcraft.extensions import apply_extensions from snapcraft.models.project import SnapcraftBuildPlanner, apply_root_packages from snapcraft.parts import set_global_environment @@ -172,6 +173,34 @@ def app_config(self) -> dict[str, Any]: config["core24"] = self._known_core24 return config + @override + def run(self) -> int: + try: + return_code = super().run() + except craft_store.errors.NoKeyringError as err: + self._emit_error( + craft_cli.errors.CraftError( + f"craft-store error: {err}", + resolution=( + "Ensure the keyring is working or " + f"{store.constants.ENVIRONMENT_STORE_CREDENTIALS} " + "is correctly exported into the environment" + ), + docs_url="https://snapcraft.io/docs/snapcraft-authentication", + ) + ) + return_code = 1 + except craft_store.errors.CraftStoreError as err: + self._emit_error( + craft_cli.errors.CraftError( + f"craft-store error: {err}", resolution=err.resolution + ), + cause=err, + ) + return_code = 1 + + return return_code + @override def _setup_partitions(self, yaml_data: dict[str, Any]) -> list[str] | None: components = models.ComponentProject.unmarshal(yaml_data) diff --git a/tests/spread/core24/package-filter/snapcraft.yaml b/tests/spread/core24/package-filter/snapcraft.yaml new file mode 100644 index 0000000000..7d5d2cfe29 --- /dev/null +++ b/tests/spread/core24/package-filter/snapcraft.yaml @@ -0,0 +1,16 @@ +name: package-filter +summary: test package filtering +description: | + Verify that some packages are pulled in as stage-packages even though they are + present in the base. +version: "1.0" +grade: devel +confinement: strict +base: core24 + +parts: + nil: + plugin: nil + stage-packages: + - python3-cffi + - python3-jsonschema diff --git a/tests/spread/core24/package-filter/task.yaml b/tests/spread/core24/package-filter/task.yaml new file mode 100644 index 0000000000..6a4dd8fbb1 --- /dev/null +++ b/tests/spread/core24/package-filter/task.yaml @@ -0,0 +1,14 @@ +summary: Test the package filtering in core24 + +restore: | + snapcraft clean --destructive-mode + +execute: | + snapcraft prime --destructive-mode + + # Staging "python3-cffi" should also stage "python3-cffi-backend", even though + # it's already contained in the base snap + test -e prime/usr/lib/python3/dist-packages/_cffi_backend.cpython-*-linux-gnu.so + + # Same for "python3-jsonschema": should also stage "python3-attr" + test -d prime/usr/lib/python3/dist-packages/attr diff --git a/tests/unit/test_application.py b/tests/unit/test_application.py index bbeb46e22b..0162aac494 100644 --- a/tests/unit/test_application.py +++ b/tests/unit/test_application.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . """Unit tests for application classes.""" + import json import os import sys @@ -21,6 +22,7 @@ import craft_cli import craft_parts.plugins +import craft_store import pytest import yaml from craft_application import util @@ -539,3 +541,52 @@ def test_known_core24(snapcraft_yaml, base, build_base, is_known_core24): app = application.create_app() assert app._known_core24 == is_known_core24 + + +@pytest.mark.parametrize( + ("message", "resolution", "expected_message"), + [ + ( + "error message", + "error resolution", + "error message\nRecommended resolution: error resolution", + ), + ("error message", None, "error message"), + ], +) +def test_store_error(mocker, capsys, message, resolution, expected_message): + mocker.patch( + "snapcraft.application.Application.run", + side_effect=craft_store.errors.CraftStoreError(message, resolution=resolution), + ) + + return_code = application.main() + + assert return_code == 1 + _, err = capsys.readouterr() + assert f"craft-store error: {expected_message}" in err + + +def test_store_key_error(mocker, capsys): + mocker.patch( + "snapcraft.application.Application.run", + side_effect=craft_store.errors.NoKeyringError(), + ) + + return_code = application.main() + + assert return_code == 1 + _, err = capsys.readouterr() + assert err.startswith( + # There is merit in showing the line as it would be printed out. + # If it is too long here it needs fixing at the source. + # pylint: disable=[line-too-long] + dedent( + """\ + craft-store error: No keyring found to store or retrieve credentials from. + Recommended resolution: Ensure the keyring is working or SNAPCRAFT_STORE_CREDENTIALS is correctly exported into the environment + For more information, check out: https://snapcraft.io/docs/snapcraft-authentication + """ + # pylint: enable=[line-too-long] + ) + )