Skip to content

Commit

Permalink
feat(remote-build): check base before executing (#4343)
Browse files Browse the repository at this point in the history
Only core20 and core22 bases can use the fallback remote build behavior.

Signed-off-by: Callahan Kovacs <callahan.kovacs@canonical.com>
  • Loading branch information
mr-cal authored Sep 5, 2023
1 parent 7bcd1eb commit 128e0ac
Show file tree
Hide file tree
Showing 3 changed files with 280 additions and 139 deletions.
63 changes: 49 additions & 14 deletions snapcraft/commands/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
from craft_cli.helptexts import HIDDEN
from overrides import overrides

from snapcraft.errors import MaintenanceBase, SnapcraftError
from snapcraft.legacy_cli import run_legacy
from snapcraft.parts.yaml_utils import get_snap_project, process_yaml
from snapcraft.parts import yaml_utils
from snapcraft.utils import confirm_with_user
from snapcraft_legacy.internal.remote_build.errors import AcceptPublicUploadError

Expand Down Expand Up @@ -88,15 +89,58 @@ def fill_parser(self, parser: argparse.ArgumentParser) -> None:
help="acknowledge that uploaded code will be publicly available.",
)

def _get_effective_base(self) -> str:
"""Get a valid effective base from the project's snapcraft.yaml.
:returns: The project's effective base.
:raises SnapcraftError: If the base is unknown or missing or if the
snapcraft.yaml cannot be loaded.
:raises MaintenanceBase: If the base is not supported
"""
snapcraft_yaml = yaml_utils.get_snap_project().project_file

with open(snapcraft_yaml, encoding="utf-8") as file:
base = yaml_utils.get_base(file)

if base is None:
raise SnapcraftError(
f"Could not determine base from {str(snapcraft_yaml)!r}."
)

emit.debug(f"Got base {base!r} from {str(snapcraft_yaml)!r}.")

if base in yaml_utils.ESM_BASES:
raise MaintenanceBase(base)

if base not in yaml_utils.BASES:
raise SnapcraftError(f"Unknown base {base!r} in {str(snapcraft_yaml)!r}.")

return base

def _run_remote_build(self, base: str) -> None:
# bases newer than core22 must use the new remote-build
if base in yaml_utils.CURRENT_BASES - {"core22"}:
emit.debug(
"Using fallback remote-build because new remote-build is not available."
)
# TODO: use new remote-build code (#4323)
run_legacy()
return

emit.debug("Running fallback remote-build.")
run_legacy()

@overrides
def run(self, parsed_args):
def run(self, parsed_args) -> None:
if os.getenv("SUDO_USER") and os.geteuid() == 0:
emit.message(
"Running with 'sudo' may cause permission errors and is discouraged."
)

emit.message(
"snapcraft remote-build is experimental and is subject to change - use with caution."
"snapcraft remote-build is experimental and is subject to change "
"- use with caution."
)

if parsed_args.build_on:
Expand All @@ -108,14 +152,5 @@ def run(self, parsed_args):
):
raise AcceptPublicUploadError()

snap_project = get_snap_project()
# TODO proper core22 support would mean we need to load the project
# yaml_data = process_yaml(snap_project.project_file)
# for now, only log explicitly that we are falling back to legacy to
# remote build for core22
process_yaml(snap_project.project_file)

emit.debug(
"core22 not yet supported in new code base: re-executing into legacy for remote-build"
)
run_legacy()
base = self._get_effective_base()
self._run_remote_build(base)
15 changes: 11 additions & 4 deletions snapcraft/parts/yaml_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,15 @@

_CORE_PART_KEYS = ["build-packages", "build-snaps"]
_CORE_PART_NAME = "snapcraft/core"
_ESM_BASES = {"core", "core18"}
_LEGACY_BASES = {"core20"}

# All bases recognized by snapcraft
BASES = {"core", "core18", "core20", "core22", "devel"}
# Bases no longer supported by the current version of snapcraft
ESM_BASES = {"core", "core18"}
# Bases handled by the legacy snapcraft codebase
LEGACY_BASES = {"core20"}
# Bases handled by the current snapcraft codebase
CURRENT_BASES = BASES - ESM_BASES - LEGACY_BASES


@dataclass
Expand Down Expand Up @@ -133,9 +140,9 @@ def load(filestream: TextIO) -> Dict[str, Any]:

if build_base is None:
raise errors.LegacyFallback("no base defined")
if build_base in _ESM_BASES:
if build_base in ESM_BASES:
raise errors.MaintenanceBase(build_base)
if build_base in _LEGACY_BASES:
if build_base in LEGACY_BASES:
raise errors.LegacyFallback(f"base is {build_base}")

filestream.seek(0)
Expand Down
Loading

0 comments on commit 128e0ac

Please sign in to comment.