Repository: beeware/briefcase
Pull request #1272 (2023-05-14 18:58:35)

Move default Flatpak runtime to `pyproject.toml` and upgrade to Freedesktop 22.08
## Changes
- Updates the default Flatpak runtime from Freedesktop 21.08 -> 22.08
- Additionally, this default runtime will now be set in `pyproject.toml` at project creation
  - https://github.com/beeware/briefcase-template/pull/68

## PR Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
- [x] All new features have been tested
- [x] All new features have been documented
- [x] I have read the **CONTRIBUTING.md** file
- [x] I will abide by the code of conduct



Patch:
diff --git a/changes/1272.removal.rst b/changes/1272.removal.rst
new file mode 100644
index 00000000..e070e585
--- /dev/null
+++ b/changes/1272.removal.rst
@@ -0,0 +1,1 @@
+Flatpak apps no longer default to using the Freedesktop runtime and SDK version 21.08 when a runtime is not specified. Instead, the runtime now must be explicitly defined in the `application configuration <https://briefcase.readthedocs.io/en/latest/reference/platforms/linux/flatpak.html#application-configuration>`__.
diff --git a/changes/1273.misc.rst b/changes/1273.misc.rst
deleted file mode 100644
index 276556ea..00000000
--- a/changes/1273.misc.rst
+++ /dev/null
@@ -1,1 +0,0 @@
-Updated pytest-xdist from 3.2.1 to 3.3.0.
diff --git a/docs/reference/platforms/linux/flatpak.rst b/docs/reference/platforms/linux/flatpak.rst
index 43d9d21f..ee025f1f 100644
--- a/docs/reference/platforms/linux/flatpak.rst
+++ b/docs/reference/platforms/linux/flatpak.rst
@@ -84,29 +84,26 @@ runtime repository.
 ``flatpak_runtime``
 ~~~~~~~~~~~~~~~~~~~
 
-A string, identifying the runtime to use as a base for the Flatpak app. By
-default, Flatpaks build with Briefcase will use the ``org.freedesktop.Platform``
-runtime.
+A string, identifying the `runtime
+<https://docs.flatpak.org/en/latest/available-runtimes.html>`__ to use as a
+base for the Flatpak app.
 
-The Flatpak runtime and SDK are paired; so if you define ``flatpak_runtime``,
-you *must* also define ``flatpak_sdk``.
+The Flatpak runtime and SDK are paired; so, both a ``flatpak_runtime`` and a
+corresponding ``flatpak_sdk`` must be defined.
 
 ``flatpak_runtime_version``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 A string, identifying the version of the Flatpak runtime that should be used.
-Flatpaks built with Briefcase will use version ``21.08`` of the FreeDesktop
-platform runtime.
 
 ``flatpak_sdk``
 ~~~~~~~~~~~~~~~
 
 A string, identifying the SDK associated with the platform that will be used to
-build the Flatpak app. By default, Flatpaks build with Briefcase will use the
-``org.freedesktop.Sdk`` SDK. The SDK will use the same version as the runtime.
+build the Flatpak app.
 
-The Flatpak runtime and SDK are paired; so if you define ``flatpak_sdk``,
-you *must* also define ``flatpak_runtime``.
+The Flatpak runtime and SDK are paired; so, both a ``flatpak_runtime`` and a
+corresponding ``flatpak_sdk`` must be defined.
 
 Compilation issues with Flatpak
 ===============================
diff --git a/pyproject.toml b/pyproject.toml
index b0ce2512..8a3bf1a2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -67,3 +67,10 @@ filename = "docs/background/releases.rst"
 title_format = "{version} ({project_date})"
 issue_format = "`#{issue} <https://github.com/beeware/briefcase/issues/{issue}>`__"
 template = "changes/template.rst"
+type = [
+    { directory = "feature", name = "Features", showcontent = true },
+    { directory = "bugfix", name = "Bugfixes", showcontent = true },
+    { directory = "removal", name = "Backward Incompatible Changes", showcontent = true },
+    { directory = "doc", name = "Documentation", showcontent = true },
+    { directory = "misc", name = "Misc", showcontent = false },
+ ]
diff --git a/setup.cfg b/setup.cfg
index 45cc3481..c1f396a6 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -92,7 +92,7 @@ dev =
     coverage-conditional-plugin == 0.8.0
     pre-commit == 3.3.1
     pytest == 7.3.1
-    pytest-xdist == 3.3.0
+    pytest-xdist == 3.2.1
     setuptools_scm[toml] == 7.1.0
     tox == 4.5.1
 docs =
diff --git a/src/briefcase/integrations/flatpak.py b/src/briefcase/integrations/flatpak.py
index f397843a..20c5a2eb 100644
--- a/src/briefcase/integrations/flatpak.py
+++ b/src/briefcase/integrations/flatpak.py
@@ -11,10 +11,6 @@ class Flatpak(Tool):
     DEFAULT_REPO_ALIAS = "flathub"
     DEFAULT_REPO_URL = "https://flathub.org/repo/flathub.flatpakrepo"
 
-    DEFAULT_RUNTIME = "org.freedesktop.Platform"
-    DEFAULT_RUNTIME_VERSION = "21.08"
-    DEFAULT_SDK = "org.freedesktop.Sdk"
-
     def __init__(self, tools: ToolCache):
         self.tools = tools
 
diff --git a/src/briefcase/platforms/linux/flatpak.py b/src/briefcase/platforms/linux/flatpak.py
index 4cabff4f..3f8cdaee 100644
--- a/src/briefcase/platforms/linux/flatpak.py
+++ b/src/briefcase/platforms/linux/flatpak.py
@@ -61,35 +61,43 @@ class LinuxFlatpakMixin(LinuxMixin):
         return repo_alias, repo_url
 
     def flatpak_runtime(self, app):
-        # Verify that either both or neither of runtime *and* sdk are specified
         try:
-            runtime = app.flatpak_runtime
-            if hasattr(app, "flatpak_sdk"):
-                return runtime
-            else:
-                raise BriefcaseConfigError(
-                    "If you specify a custom Flatpak runtime, "
-                    "you must also specify a corresponding Flatpak SDK."
-                )
-        except AttributeError:
-            return Flatpak.DEFAULT_RUNTIME
+            return app.flatpak_runtime
+        except AttributeError as e:
+            raise BriefcaseConfigError(
+                """\
+The App does not specify the Flatpak runtime to use.
+
+Your application configuration must provide values for
+`flatpak_sdk`, `flatpak_runtime`, and `flatpak_runtime_version`.
+"""
+            ) from e
 
     def flatpak_runtime_version(self, app):
-        return getattr(app, "flatpak_runtime_version", Flatpak.DEFAULT_RUNTIME_VERSION)
+        try:
+            return app.flatpak_runtime_version
+        except AttributeError as e:
+            raise BriefcaseConfigError(
+                """\
+The App does not specify the version of the Flatpak runtime to use.
+
+Your application configuration must provide values for
+`flatpak_sdk`, `flatpak_runtime`, and `flatpak_runtime_version`.
+"""
+            ) from e
 
     def flatpak_sdk(self, app):
-        # Verify that either both or neither of runtime *and* sdk are specified
         try:
-            sdk = app.flatpak_sdk
-            if hasattr(app, "flatpak_runtime"):
-                return sdk
-            else:
-                raise BriefcaseConfigError(
-                    "If you specify a custom Flatpak SDK, "
-                    "you must also specify a corresponding Flatpak runtime."
-                )
-        except AttributeError:
-            return Flatpak.DEFAULT_SDK
+            return app.flatpak_sdk
+        except AttributeError as e:
+            raise BriefcaseConfigError(
+                """\
+The App does not specify the Flatpak SDK to use.
+
+Your application configuration must provide values for
+`flatpak_sdk`, `flatpak_runtime`, and `flatpak_runtime_version`.
+"""
+            ) from e
 
 
 class LinuxFlatpakCreateCommand(LinuxFlatpakMixin, CreateCommand):


Test patch:
diff --git a/tests/platforms/linux/conftest.py b/tests/platforms/linux/conftest.py
index 4f6207f0..a508abbe 100644
--- a/tests/platforms/linux/conftest.py
+++ b/tests/platforms/linux/conftest.py
@@ -7,7 +7,7 @@ from briefcase.platforms.linux import LinuxMixin
 
 @pytest.fixture
 def linux_mixin():
-    "A Linux mixin with a mocked tools collection"
+    """A Linux mixin with a mocked tools collection."""
     linux_mixin = LinuxMixin()
     linux_mixin.tools = MagicMock()
     return linux_mixin
diff --git a/tests/platforms/linux/flatpak/test_build.py b/tests/platforms/linux/flatpak/test_build.py
index 6149025f..cb2aa936 100644
--- a/tests/platforms/linux/flatpak/test_build.py
+++ b/tests/platforms/linux/flatpak/test_build.py
@@ -1,8 +1,9 @@
-from unittest import mock
+from unittest.mock import MagicMock
 
 import pytest
 
 from briefcase.console import Console, Log
+from briefcase.exceptions import BriefcaseConfigError
 from briefcase.integrations.flatpak import Flatpak
 from briefcase.platforms.linux.flatpak import LinuxFlatpakBuildCommand
 
@@ -19,7 +20,7 @@ def build_command(tmp_path):
 
 def test_build(build_command, first_app_config, tmp_path):
     """A flatpak can be built."""
-    build_command.tools.flatpak = mock.MagicMock(spec_set=Flatpak)
+    build_command.tools.flatpak = MagicMock(spec_set=Flatpak)
 
     first_app_config.flatpak_runtime_repo_url = "https://example.com/flatpak/repo"
     first_app_config.flatpak_runtime_repo_alias = "custom-repo"
@@ -50,3 +51,14 @@ def test_build(build_command, first_app_config, tmp_path):
         app_name="first-app",
         path=tmp_path / "base_path" / "build" / "first-app" / "linux" / "flatpak",
     )
+
+
+def test_missing_runtime_config(build_command, first_app_config):
+    """The app build errors is a Flatpak runtime is not defined."""
+    build_command.tools.flatpak = MagicMock(spec_set=Flatpak)
+
+    with pytest.raises(
+        BriefcaseConfigError,
+        match="Briefcase configuration error: The App does not specify the Flatpak runtime to use",
+    ):
+        build_command.build_app(first_app_config)
diff --git a/tests/platforms/linux/flatpak/test_create.py b/tests/platforms/linux/flatpak/test_create.py
index 983296af..0f977a8d 100644
--- a/tests/platforms/linux/flatpak/test_create.py
+++ b/tests/platforms/linux/flatpak/test_create.py
@@ -1,7 +1,10 @@
+from unittest.mock import MagicMock
+
 import pytest
 
 from briefcase.console import Console, Log
-from briefcase.exceptions import UnsupportedHostError
+from briefcase.exceptions import BriefcaseConfigError, UnsupportedHostError
+from briefcase.integrations.flatpak import Flatpak
 from briefcase.platforms.linux.flatpak import LinuxFlatpakCreateCommand
 
 
@@ -27,7 +30,7 @@ def test_unsupported_host_os(create_command, host_os):
         create_command()
 
 
-def test_output_format_template_context(create_command, first_app_config, tmp_path):
+def test_output_format_template_context(create_command, first_app_config):
     """The template context is provided flatpak details."""
     first_app_config.flatpak_runtime = "org.beeware.Platform"
     first_app_config.flatpak_runtime_version = "37.42"
@@ -38,3 +41,14 @@ def test_output_format_template_context(create_command, first_app_config, tmp_pa
         "flatpak_runtime_version": "37.42",
         "flatpak_sdk": "org.beeware.SDK",
     }
+
+
+def test_missing_runtime_config(create_command, first_app_config):
+    """The app creation errors is a Flatpak runtime is not defined."""
+    create_command.tools.flatpak = MagicMock(spec_set=Flatpak)
+
+    with pytest.raises(
+        BriefcaseConfigError,
+        match="Briefcase configuration error: The App does not specify the Flatpak runtime to use",
+    ):
+        create_command.output_format_template_context(first_app_config)
diff --git a/tests/platforms/linux/flatpak/test_mixin.py b/tests/platforms/linux/flatpak/test_mixin.py
index 379534c9..040e1f23 100644
--- a/tests/platforms/linux/flatpak/test_mixin.py
+++ b/tests/platforms/linux/flatpak/test_mixin.py
@@ -54,13 +54,13 @@ def test_distribution_path(create_command, first_app_config, tmp_path):
     assert distribution_path == expected_path
 
 
-def test_default_runtime_repo(create_command, first_app_config, tmp_path):
+def test_default_runtime_repo(create_command, first_app_config):
     """The flathub repository is the default runtime repository."""
     expected_repo = ("flathub", "https://flathub.org/repo/flathub.flatpakrepo")
     assert create_command.flatpak_runtime_repo(first_app_config) == expected_repo
 
 
-def test_custom_runtime_repo(create_command, first_app_config, tmp_path):
+def test_custom_runtime_repo(create_command, first_app_config):
     """A custom runtime repo can be specified."""
     first_app_config.flatpak_runtime_repo_alias = "custom_repo"
     first_app_config.flatpak_runtime_repo_url = "https://example.com/flatpak/runtime"
@@ -69,7 +69,7 @@ def test_custom_runtime_repo(create_command, first_app_config, tmp_path):
     assert create_command.flatpak_runtime_repo(first_app_config) == expected_repo
 
 
-def test_custom_runtime_repo_no_alias(create_command, first_app_config, tmp_path):
+def test_custom_runtime_repo_no_alias(create_command, first_app_config):
     """If a custom runtime repo URL is specified, an alias must be specified as well."""
     first_app_config.flatpak_runtime_repo_url = "https://example.com/flatpak/runtime"
 
@@ -80,17 +80,7 @@ def test_custom_runtime_repo_no_alias(create_command, first_app_config, tmp_path
         create_command.flatpak_runtime_repo(first_app_config)
 
 
-def test_default_runtime_config(create_command, first_app_config, tmp_path):
-    """Flatpak apps use a default runtime configuration."""
-
-    assert (
-        create_command.flatpak_runtime(first_app_config) == "org.freedesktop.Platform"
-    )
-    assert create_command.flatpak_runtime_version(first_app_config) == "21.08"
-    assert create_command.flatpak_sdk(first_app_config) == "org.freedesktop.Sdk"
-
-
-def test_custom_runtime(create_command, first_app_config, tmp_path):
+def test_custom_runtime(create_command, first_app_config):
     """A custom runtime can be specified."""
     first_app_config.flatpak_runtime = "org.beeware.Platform"
     first_app_config.flatpak_runtime_version = "37.42"
@@ -101,31 +91,43 @@ def test_custom_runtime(create_command, first_app_config, tmp_path):
     assert create_command.flatpak_sdk(first_app_config) == "org.beeware.SDK"
 
 
-def test_custom_runtime_runtime_only(create_command, first_app_config, tmp_path):
-    """If the user only defines a runtime, accessing the SDK raises an error."""
-    first_app_config.flatpak_runtime = "org.beeware.Platform"
+def test_missing_runtime(create_command, first_app_config):
+    """Error if App config is missing the runtime."""
     first_app_config.flatpak_runtime_version = "37.42"
+    first_app_config.flatpak_sdk = "org.beeware.SDK"
 
     with pytest.raises(
         BriefcaseConfigError,
-        match=r"If you specify a custom Flatpak runtime, you must also specify a corresponding Flatpak SDK.",
+        match="Briefcase configuration error: The App does not specify the Flatpak runtime to use",
     ):
         create_command.flatpak_runtime(first_app_config)
 
 
-def test_custom_runtime_sdk_only(create_command, first_app_config, tmp_path):
-    """If the user only defines an SDK, accessing the runtime raises an error."""
+def test_missing_sdk(create_command, first_app_config):
+    """Error if App config is missing the SDK."""
+    first_app_config.flatpak_runtime = "org.beeware.Platform"
     first_app_config.flatpak_runtime_version = "37.42"
-    first_app_config.flatpak_sdk = "org.beeware.SDK"
 
     with pytest.raises(
         BriefcaseConfigError,
-        match=r"If you specify a custom Flatpak SDK, you must also specify a corresponding Flatpak runtime.",
+        match="Briefcase configuration error: The App does not specify the Flatpak SDK to use",
     ):
         create_command.flatpak_sdk(first_app_config)
 
 
-def test_verify_linux(create_command, tmp_path):
+def test_missing_runtime_version(create_command, first_app_config):
+    """Error if App config is missing the runtime version."""
+    first_app_config.flatpak_runtime = "org.beeware.Platform"
+    first_app_config.flatpak_sdk = "org.beeware.SDK"
+
+    with pytest.raises(
+        BriefcaseConfigError,
+        match="Briefcase configuration error: The App does not specify the version of the Flatpak runtime to use",
+    ):
+        create_command.flatpak_runtime_version(first_app_config)
+
+
+def test_verify_linux(create_command):
     """Verifying on Linux creates an SDK wrapper."""
     create_command.tools.host_os = "Linux"
     create_command.tools.subprocess = MagicMock(spec_set=Subprocess)