Skip to content

Commit

Permalink
fix: re-register dotnet for core22 (#4841)
Browse files Browse the repository at this point in the history
Signed-off-by: Callahan Kovacs <[email protected]>
  • Loading branch information
mr-cal authored Jun 10, 2024
1 parent 00fa0ac commit f8cf313
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 26 deletions.
64 changes: 43 additions & 21 deletions snapcraft/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,11 @@ def _get_esm_error_for_base(base: str) -> None:
class Snapcraft(Application):
"""Snapcraft application definition."""

_known_core24: bool
"""True if the project should use the core24/craft-application codepath."""

def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
# Whether we know that we should use the core24-based codepath.
self._known_core24 = False
self._parse_info: dict[str, list[str]] = {}

# Locate the project file. It's used in early execution to determine
Expand All @@ -99,22 +100,40 @@ def __init__(self, *args, **kwargs) -> None:
self._snapcraft_yaml_path: pathlib.Path | None = self._resolve_project_path(
None
)
with self._snapcraft_yaml_path.open() as file:
self._snapcraft_yaml_data = util.safe_yaml_load(file)
except FileNotFoundError:
self._snapcraft_yaml_path = None
self._snapcraft_yaml_path = self._snapcraft_yaml_data = None

self._known_core24 = self._get_known_core24()

for craft_var, snapcraft_var in MAPPED_ENV_VARS.items():
if env_val := os.getenv(snapcraft_var):
os.environ[craft_var] = env_val

def _get_known_core24(self) -> bool:
"""Return true if the project is known to be core24."""
if self._snapcraft_yaml_data:
base = self._snapcraft_yaml_data.get("base")
build_base = self._snapcraft_yaml_data.get("build-base")

# We know for sure that we're handling a core24 project
if "core24" in (base, build_base) or build_base == "devel":
return True

return False

def _get_app_plugins(self) -> dict[str, PluginType]:
return plugins.get_plugins(core22=False)

@override
def _register_default_plugins(self) -> None:
"""Register per application plugins when initializing."""
super()._register_default_plugins()
# dotnet is disabled for core24 because it is pending a rewrite
craft_parts.plugins.unregister("dotnet")

if self._known_core24:
# dotnet is disabled for core24 and newer because it is pending a rewrite
craft_parts.plugins.unregister("dotnet")

@override
def _configure_services(self, provider_name: str | None) -> None:
Expand Down Expand Up @@ -181,22 +200,23 @@ def _extra_yaml_transform(

@override
def _get_dispatcher(self) -> craft_cli.Dispatcher:
# Handle "multiplexing" of Snapcraft "codebases" depending on the
# project's base (if any). Here, we handle the case where there *is*
# a project and it's core24, which means it should definitely fall into
# the craft-application-based flow.
if self._snapcraft_yaml_path:
with self._snapcraft_yaml_path.open() as file:
yaml_data = util.safe_yaml_load(file)
base = yaml_data.get("base")
build_base = yaml_data.get("build-base")
"""Handle multiplexing of Snapcraft "codebases" depending on the project's base.
The ClassicFallback-based flow is used in any of the following scenarios:
- there is no project to load
- for core20 remote builds if SNAPCRAFT_REMOTE_BUILD_STRATEGY is not "disable-fallback"
- for core22 remote builds if SNAPCRAFT_REMOTE_BUILD_STRATEGY is "force-fallback"
The craft-application-based flow is used in any of the following scenarios:
- the project base is core24 or newer
- for the "version" command
"""
if self._snapcraft_yaml_data:
base = self._snapcraft_yaml_data.get("base")
build_base = self._snapcraft_yaml_data.get("build-base")
_get_esm_error_for_base(base)
if "core24" in (base, build_base) or build_base == "devel":
# We know for sure that we're handling a core24 project
self._known_core24 = True
elif any(arg in ("version", "--version", "-V") for arg in sys.argv):
pass
elif "remote-build" in sys.argv and any(

if "remote-build" in sys.argv and any(
b in ("core20", "core22") for b in (base, build_base)
):
build_strategy = os.environ.get("SNAPCRAFT_REMOTE_BUILD_STRATEGY", None)
Expand All @@ -223,7 +243,9 @@ def _get_dispatcher(self) -> craft_cli.Dispatcher:
and build_strategy == "force-fallback"
):
raise errors.ClassicFallback()
else:
elif not self._known_core24 and not any(
arg in ("version", "--version", "-V") for arg in sys.argv
):
raise errors.ClassicFallback()
return super()._get_dispatcher()

Expand Down
18 changes: 18 additions & 0 deletions tests/spread/core24/dotnet/snapcraft.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: dotnet-hello
base: core24
version: '1.0'
summary: a simple dotnet snap
description: a simple dotnet snap

confinement: strict

apps:
dotnet-hello:
command: dotnet

parts:
hello:
plugin: dotnet
source: .
dotnet-self-contained-runtime-identifier: linux-x64
build-snaps: [dotnet-sdk]
11 changes: 11 additions & 0 deletions tests/spread/core24/dotnet/task.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
summary: Build a snap with the dotnet plugin

restore: |
rm -rf ./*.snap
execute: |
# Unset SNAPCRAFT_BUILD_ENVIRONMENT=host.
unset SNAPCRAFT_BUILD_ENVIRONMENT
# dotnet is disabled for core24 until the dotnet sdk snap is rewritten
snapcraft pack 2>&1 | MATCH "plugin not registered: 'dotnet'"
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Console.WriteLine("hello world");
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: dotnet-hello
base: core22
version: '1.0'
summary: a simple dotnet snap
description: a simple dotnet snap

confinement: strict

apps:
dotnet-hello:
command: dotnet

parts:
hello:
plugin: dotnet
source: .
dotnet-self-contained-runtime-identifier: linux-x64
build-snaps: [dotnet-sdk]
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ environment:
SNAP/python: python-hello
SNAP/qmake: qmake-hello
SNAP/maven: maven-hello
SNAP/dotnet: dotnet-hello

prepare: |
#shellcheck source=tests/spread/tools/snapcraft-yaml.sh
Expand All @@ -28,6 +29,7 @@ restore: |
# Undo changes to hello
[ -f hello ] && git checkout hello
[ -f hello.c ] && git checkout hello.c
[ -f hello.cs ] && git checkout hello.cs
[ -f subdir/hello.c ] && git checkout subdir/hello.c
[ -f hello.js ] && git checkout hello.js
[ -f main.go ] && git checkout main.go
Expand Down Expand Up @@ -72,6 +74,8 @@ execute: |
modified_file=hello
elif [ -f hello.c ]; then
modified_file=hello.c
elif [ -f hello.cs ]; then
modified_file=hello.cs
elif [ -f subdir/hello.c ]; then
modified_file=subdir/hello.c
elif [ -f hello.js ]; then
Expand Down
9 changes: 8 additions & 1 deletion tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

import pytest
import yaml
from craft_parts import Features, callbacks
from craft_parts import Features, callbacks, plugins
from craft_providers import Executor, Provider
from craft_providers.base import Base
from overrides import override
Expand All @@ -37,6 +37,13 @@ def unregister_callbacks(mocker):
callbacks.unregister_all()


@pytest.fixture(autouse=True)
def reset_plugins():
# craft-part modifies a dictionary of plugins that doesn't get reloaded between tests
# 'unregister_all()' resets to the dictionary to the default value
plugins.unregister_all()


@pytest.fixture
def snapcraft_yaml(new_dir):
"""Return a fixture that can write a snapcraft.yaml."""
Expand Down
64 changes: 60 additions & 4 deletions tests/unit/test_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from textwrap import dedent

import craft_cli
import craft_parts.plugins
import pytest
import yaml
from craft_application import util
Expand Down Expand Up @@ -309,13 +310,45 @@ def test_application_plugins():
assert "kernel" not in plugins


def test_application_dotnet_not_registered():
"""dotnet plugin is disable for core24."""
@pytest.mark.parametrize(
("base", "build_base"),
[
("core20", None),
("core20", "core20"),
("core20", "devel"),
("core22", None),
("core22", "core22"),
("core22", "devel"),
],
)
def test_application_dotnet_registered(base, build_base, snapcraft_yaml):
"""dotnet plugin is enabled for core22."""
snapcraft_yaml(base=base, build_base=build_base)
app = application.create_app()

plugins = app._get_app_plugins()
app._register_default_plugins()

assert "dotnet" in craft_parts.plugins.get_registered_plugins()


@pytest.mark.parametrize(
("base", "build_base"),
[
("core24", None),
("core24", "core20"),
("core24", "core22"),
("core24", "core24"),
("core24", "devel"),
],
)
def test_application_dotnet_not_registered(base, build_base, snapcraft_yaml):
"""dotnet plugin is disabled for core24 and newer bases."""
snapcraft_yaml(base=base, build_base=build_base)
app = application.create_app()

assert "dotnet" not in plugins
app._register_default_plugins()

assert "dotnet" not in craft_parts.plugins.get_registered_plugins()


def test_default_command_integrated(monkeypatch, mocker, new_dir):
Expand Down Expand Up @@ -484,3 +517,26 @@ def test_run_envvar_invalid(snapcraft_yaml, base, monkeypatch):
"'SNAPCRAFT_REMOTE_BUILD_STRATEGY'. Valid values are 'disable-fallback' and "
"'force-fallback'"
)


@pytest.mark.parametrize(
("base", "build_base", "is_known_core24"),
[
("core20", None, False),
("core20", "core20", False),
("core20", "devel", False),
("core22", None, False),
("core22", "core22", False),
("core22", "devel", False),
("core24", "core22", True),
("core24", None, True),
("core24", "core24", True),
("core24", "devel", True),
],
)
def test_known_core24(snapcraft_yaml, base, build_base, is_known_core24):
snapcraft_yaml(base=base, build_base=build_base)

app = application.create_app()

assert app._known_core24 == is_known_core24

0 comments on commit f8cf313

Please sign in to comment.