[PR #11748/972bed66 backport][stable-12] flatpak: add from_url parameter, deprecate URLs in name (#11814)

flatpak: add from_url parameter, deprecate URLs in name (#11748)

* flatpak: add from_url parameter, deprecate URLs in name

Adds a new `from_url` parameter for installing flatpaks from a
.flatpakref URL, using `flatpak install --from <url>`. The `name`
parameter then carries the reverse DNS application ID, enabling
reliable idempotency checks.

Passing URLs directly in `name` is now deprecated and will be
removed in community.general 14.0.0.

Fixes #4000



* flatpak: add changelog fragment for PR #11748



* flatpak: remove deprecation, adjust docs tone



* flatpak: add integration tests for from_url parameter



---------


(cherry picked from commit 972bed66f4)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
patchback[bot]
2026-04-13 21:30:31 +02:00
committed by GitHub
parent e278490fe7
commit 32c4bbea30
4 changed files with 189 additions and 16 deletions

View File

@@ -0,0 +1,4 @@
minor_changes:
- flatpak - add new parameter ``from_url`` to install a flatpak from a ``.flatpakref`` URL
(https://github.com/ansible-collections/community.general/issues/4000,
https://github.com/ansible-collections/community.general/pull/11748).

View File

@@ -45,18 +45,27 @@ options:
name:
description:
- The name of the flatpak to manage. To operate on several packages this can accept a list of packages.
- When used with O(state=present), O(name) can be specified as a URL to a C(flatpakref) file or the unique reverse DNS
name that identifies a flatpak.
- Both C(https://) and C(http://) URLs are supported.
- Should be specified as the unique reverse DNS name that identifies a flatpak (for example V(org.gnome.gedit)).
- When supplying a reverse DNS name, you can use the O(remote) option to specify on what remote to look for the flatpak.
An example for a reverse DNS name is C(org.gnome.gedit).
- When used with O(state=absent) or O(state=latest), it is recommended to specify the name in the reverse DNS format.
- When used with O(state=present), O(name) can also be specified as a C(https://) or C(http://) URL to a C(flatpakref) file.
However, it is recommended you use O(from_url) instead to get reliable idempotency.
Passing URLs in O(name) will be deprecated in the future.
- When used with O(state=absent) or O(state=latest), always specify the name in the reverse DNS format.
- When supplying a URL with O(state=absent) or O(state=latest), the module tries to match the installed flatpak based
on the name of the flatpakref to remove or update it. However, there is no guarantee that the names of the flatpakref
file and the reverse DNS name of the installed flatpak do match.
type: list
elements: str
required: true
from_url:
description:
- A C(http://) or C(https://) URL pointing to a C(.flatpakref) file to install from.
- When this option is set, O(name) must contain exactly one entry specifying the reverse DNS application ID of the
flatpak (for example V(com.onepassword.OnePassword)). This is used to check whether the flatpak is already installed.
- O(name) and O(from_url) cannot both contain URLs.
- This option is recommended instead of passing a URL in O(name); passing URLs in O(name) will be deprecated in the future.
type: str
version_added: "12.6.0"
no_dependencies:
description:
- If installing runtime dependencies should be omitted or not.
@@ -84,12 +93,14 @@ options:
EXAMPLES = r"""
- name: Install the spotify flatpak
community.general.flatpak:
name: https://s3.amazonaws.com/alexlarsson/spotify-repo/spotify.flatpakref
name: com.spotify.Client
from_url: https://s3.amazonaws.com/alexlarsson/spotify-repo/spotify.flatpakref
state: present
- name: Install the gedit flatpak package without dependencies (not recommended)
community.general.flatpak:
name: https://git.gnome.org/browse/gnome-apps-nightly/plain/gedit.flatpakref
name: org.gnome.gedit
from_url: https://git.gnome.org/browse/gnome-apps-nightly/plain/gedit.flatpakref
state: present
no_dependencies: true
@@ -120,12 +131,14 @@ EXAMPLES = r"""
- name: Update the spotify flatpak
community.general.flatpak:
name: https://s3.amazonaws.com/alexlarsson/spotify-repo/spotify.flatpakref
name: com.spotify.Client
from_url: https://s3.amazonaws.com/alexlarsson/spotify-repo/spotify.flatpakref
state: latest
- name: Update the gedit flatpak package without dependencies (not recommended)
community.general.flatpak:
name: https://git.gnome.org/browse/gnome-apps-nightly/plain/gedit.flatpakref
name: org.gnome.gedit
from_url: https://git.gnome.org/browse/gnome-apps-nightly/plain/gedit.flatpakref
state: latest
no_dependencies: true
@@ -180,7 +193,7 @@ from ansible_collections.community.general.plugins.module_utils.version import L
OUTDATED_FLATPAK_VERSION_ERROR_MESSAGE = "Unknown option --columns=application"
def install_flat(module, binary, remote, names, method, no_dependencies):
def install_flat(module, binary, remote, names, method, no_dependencies, from_url=None):
"""Add new flatpaks."""
global result # pylint: disable=global-variable-not-assigned
uri_names = []
@@ -198,12 +211,16 @@ def install_flat(module, binary, remote, names, method, no_dependencies):
base_command += ["--noninteractive"]
if no_dependencies:
base_command += ["--no-deps"]
if uri_names:
command = base_command + uri_names
_flatpak_command(module, module.check_mode, command)
if id_names:
command = base_command + [remote] + id_names
if from_url:
command = base_command + ["--from", from_url]
_flatpak_command(module, module.check_mode, command)
else:
if uri_names:
command = base_command + uri_names
_flatpak_command(module, module.check_mode, command)
if id_names:
command = base_command + [remote] + id_names
_flatpak_command(module, module.check_mode, command)
result["changed"] = True
@@ -356,6 +373,7 @@ def main():
module = AnsibleModule(
argument_spec=dict(
name=dict(type="list", elements="str", required=True),
from_url=dict(type="str"),
remote=dict(type="str", default="flathub"),
method=dict(type="str", default="system", choices=["user", "system"]),
state=dict(type="str", default="present", choices=["absent", "present", "latest"]),
@@ -366,6 +384,7 @@ def main():
)
name = module.params["name"]
from_url = module.params["from_url"]
state = module.params["state"]
remote = module.params["remote"]
no_dependencies = module.params["no_dependencies"]
@@ -380,6 +399,14 @@ def main():
if not binary:
module.fail_json(msg=f"Executable '{executable}' was not found on the system.", **result)
url_names = [n for n in name if n.startswith("http://") or n.startswith("https://")]
if from_url is not None:
if not (from_url.startswith("http://") or from_url.startswith("https://")):
module.fail_json(msg="The 'from_url' parameter must be an http:// or https:// URL.", **result)
if url_names:
module.fail_json(msg="The 'name' and 'from_url' parameters cannot both contain URLs.", **result)
if len(name) != 1:
module.fail_json(msg="When 'from_url' is used, 'name' must contain exactly one entry.", **result)
module.run_command_environ_update = dict(LANGUAGE="C", LC_ALL="C")
installed, not_installed = flatpak_exists(module, binary, name, method)
@@ -389,7 +416,7 @@ def main():
if state == "latest" and installed:
update_flat(module, binary, installed, method, no_dependencies)
if state in ("present", "latest") and not_installed:
install_flat(module, binary, remote, not_installed, method, no_dependencies)
install_flat(module, binary, remote, not_installed, method, no_dependencies, from_url)
module.exit_json(**result)

View File

@@ -84,6 +84,40 @@
state=latest an absent flatpak a second time shall still mark module execution
as changed in check mode
# state=present with from_url on absent flatpak
- name: Test addition of absent flatpak with from_url (check mode)
flatpak:
name: com.dummy.App1
from_url: http://127.0.0.1:8000/repo/com.dummy.App1.flatpakref
state: present
no_dependencies: true
register: from_url_addition_result
check_mode: true
- name: Verify addition of absent flatpak with from_url test result (check mode)
assert:
that:
- from_url_addition_result is changed
msg: "Adding an absent flatpak with from_url shall mark module execution as changed"
- name: Test non-existent idempotency of addition of absent flatpak with from_url (check mode)
flatpak:
name: com.dummy.App1
from_url: http://127.0.0.1:8000/repo/com.dummy.App1.flatpakref
state: present
no_dependencies: true
register: double_from_url_addition_result
check_mode: true
- name: Verify non-existent idempotency of addition of absent flatpak with from_url test result (check mode)
assert:
that:
- double_from_url_addition_result is changed
msg: |
Adding an absent flatpak with from_url a second time shall still mark module execution
as changed in check mode
# state=present with url on absent flatpak
- name: Test addition of absent flatpak with url (check mode)
@@ -231,6 +265,23 @@
- latest_present_result is changed
msg: "state=latest an present flatpak shall mark module execution as changed"
# state=present with from_url on present flatpak
- name: Test addition with from_url of present flatpak (check mode)
flatpak:
name: com.dummy.App2
from_url: http://127.0.0.1:8000/repo/com.dummy.App2.flatpakref
state: present
no_dependencies: true
register: from_url_addition_present_result
check_mode: true
- name: Verify addition with from_url of present flatpak test result (check mode)
assert:
that:
- from_url_addition_present_result is not changed
msg: "Adding a present flatpak with from_url shall mark module execution as not changed"
# state=present with url on present flatpak
- name: Test addition with url of present flatpak (check mode)

View File

@@ -230,6 +230,97 @@
method: "{{ method }}"
no_dependencies: true
# state=present with from_url
- name: Test addition with from_url - {{ method }}
flatpak:
name: com.dummy.App1
from_url: http://127.0.0.1:8000/repo/com.dummy.App1.flatpakref
state: present
method: "{{ method }}"
no_dependencies: true
register: from_url_addition_result
- name: Verify addition with from_url test result - {{ method }}
assert:
that:
- from_url_addition_result is changed
msg: "state=present with from_url shall add flatpak when absent"
- name: Test idempotency of addition with from_url - {{ method }}
flatpak:
name: com.dummy.App1
from_url: http://127.0.0.1:8000/repo/com.dummy.App1.flatpakref
state: present
method: "{{ method }}"
no_dependencies: true
register: double_from_url_addition_result
- name: Verify idempotency of addition with from_url test result - {{ method }}
assert:
that:
- double_from_url_addition_result is not changed
msg: "state=present with from_url shall not do anything when flatpak is already present"
- name: Cleanup after state=present with from_url test - {{ method }}
flatpak:
name: com.dummy.App1
state: absent
method: "{{ method }}"
no_dependencies: true
# from_url validation failures
- name: Test from_url with URL in name fails - {{ method }}
flatpak:
name: http://127.0.0.1:8000/repo/com.dummy.App1.flatpakref
from_url: http://127.0.0.1:8000/repo/com.dummy.App1.flatpakref
state: present
method: "{{ method }}"
register: from_url_url_name_result
ignore_errors: true
- name: Verify from_url with URL in name fails - {{ method }}
assert:
that:
- from_url_url_name_result is failed
- from_url_url_name_result is not changed
msg: "from_url and URL in name shall fail"
- name: Test from_url with multiple names fails - {{ method }}
flatpak:
name:
- com.dummy.App1
- com.dummy.App2
from_url: http://127.0.0.1:8000/repo/com.dummy.App1.flatpakref
state: present
method: "{{ method }}"
register: from_url_multi_name_result
ignore_errors: true
- name: Verify from_url with multiple names fails - {{ method }}
assert:
that:
- from_url_multi_name_result is failed
- from_url_multi_name_result is not changed
msg: "from_url with multiple names shall fail"
- name: Test from_url with non-http URL fails - {{ method }}
flatpak:
name: com.dummy.App1
from_url: file:///tmp/flatpak/repo/com.dummy.App1.flatpakref
state: present
method: "{{ method }}"
register: from_url_non_http_result
ignore_errors: true
- name: Verify from_url with non-http URL fails - {{ method }}
assert:
that:
- from_url_non_http_result is failed
- from_url_non_http_result is not changed
msg: "from_url with non-http URL shall fail"
# state=present with list of packages
- name: Test addition with list - {{ method }}