From 564824e46522638493a7c91aab2d15d89ad7f4ac Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 14 Jul 2025 18:16:17 +0530 Subject: [PATCH 1/2] builder-main: Commit mirrored media as screenshot ref to exported repo This is needed to store the application icons and the mirrored screenshots (as done by appstream) to the ostree repo. This can be useful in many ways, the primary being flat-manager extracts [1] these screenshot refs and stores them in the server so that application store frontends can use their own mirrored screenshot and icon URLs. This has been for the longest time done at various downstream levels such as in buildbot [2], flatpak-github-actions [3] and vorarbeiter [4] (the successor to buildbot) but it's more user friendly to have flatpak-builder do this extra work. [1]: https://github.com/flatpak/flat-manager/commit/eff43004756c011b0a0d034a61cec84836b8e0a9 [2]: https://github.com/flathub-infra/buildbot/blob/9d8e2b5483b2e446389548446ebf9c3934380682/master/buildbot/flathub_master.py#L1081 [3]: https://github.com/flatpak/flatpak-github-actions/blob/6684584b07d86113b1acfc80b3e4667f16f617c3/flatpak-builder/index.js#L280-L286 [4]: https://github.com/flathub-infra/vorarbeiter/blob/7f2f04a562e73ba4f46044dae7c99f8e9e64a39d/justfile#L185-L189 --- doc/flatpak-builder.xml | 4 +- src/builder-main.c | 85 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/doc/flatpak-builder.xml b/doc/flatpak-builder.xml index ae52cb96..08dfb25c 100644 --- a/doc/flatpak-builder.xml +++ b/doc/flatpak-builder.xml @@ -528,7 +528,9 @@ in the appstream xml to the specified URL. The resulting files will be stored in the "screenshots" subdirectory in the app directory for versions earlier than 1.3.4 and "files/share/app-info/media" - subdirectory for newer versions. + subdirectory for newer versions. Since version 1.4.5 this + will also create a screenshot ref in the exported OSTree + repo for each architecture containing the mirrored media. diff --git a/src/builder-main.c b/src/builder-main.c index 3845a00c..606e4d33 100644 --- a/src/builder-main.c +++ b/src/builder-main.c @@ -27,6 +27,7 @@ #include #include +#include #include "libglnx.h" #include "builder-flatpak-utils.h" @@ -263,6 +264,80 @@ do_export (BuilderContext *build_context, (const gchar * const *) args->pdata, NULL); } +static gboolean +commit_screenshot_ref (const char *repo_path, + const char *app_dir_path, + const char *arch, + GError **error) +{ + g_autofree char *media_dir_path = NULL; + g_autoptr(GFile) media_dir = NULL; + g_autoptr(GFile) repo_file = NULL; + g_autoptr(OstreeRepo) repo = NULL; + g_autoptr(OstreeMutableTree) tree = NULL; + g_autoptr(GFile) tree_root = NULL; + g_autofree char *commit_checksum = NULL; + g_autofree char *ref_name = NULL; + g_autoptr(OstreeRepoCommitModifier) modifier = NULL; + gboolean ret = FALSE; + + media_dir_path = g_build_filename (app_dir_path, "files/share/app-info/media", NULL); + media_dir = g_file_new_for_path (media_dir_path); + + if (!g_file_query_exists (media_dir, NULL)) + { + g_print ("Media directory does not exist, skipping commit\n"); + return TRUE; + } + + ref_name = g_strdup_printf ("screenshots/%s", arch); + + repo_file = g_file_new_for_path (repo_path); + repo = ostree_repo_new (repo_file); + if (!ostree_repo_open (repo, NULL, error)) + return FALSE; + + modifier = ostree_repo_commit_modifier_new (OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS, + NULL, NULL, NULL); + if (!ostree_repo_prepare_transaction (repo, NULL, NULL, error)) + return FALSE; + + tree = ostree_mutable_tree_new (); + + if (!ostree_repo_write_directory_to_mtree (repo, media_dir, tree, modifier, NULL, error)) + goto out; + + if (!ostree_repo_write_mtree (repo, tree, &tree_root, NULL, error)) + goto out; + + if (!ostree_repo_write_commit (repo, + NULL, + NULL, + NULL, + NULL, + OSTREE_REPO_FILE (tree_root), + &commit_checksum, + NULL, error)) + goto out; + + ostree_repo_transaction_set_ref (repo, NULL, ref_name, commit_checksum); + + if (!ostree_repo_commit_transaction (repo, NULL, NULL, error)) + goto out; + + g_print ("Committed screenshot ref: %s (%s)\n", ref_name, commit_checksum); + ret = TRUE; + +out: + if (!ret && repo) + { + if (!ostree_repo_abort_transaction (repo, NULL, NULL)) + g_warning ("Failed to abort ostree transaction"); + } + + return ret; +} + static gboolean do_install (BuilderContext *build_context, const gchar *repodir, @@ -974,6 +1049,16 @@ main (int argc, return 1; } + if (opt_mirror_screenshots_url && + !commit_screenshot_ref (flatpak_file_get_path_cached (export_repo), + app_dir_path, + builder_context_get_arch (build_context), + &error)) + { + g_printerr ("Failed to commit screenshot ref: %s\n", error->message); + return 1; + } + /* Export regular locale extensions */ dir_enum = g_file_enumerate_children (app_dir, "standard::name,standard::type", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, From 0db07522e5fba4920edde9823e0cf1b63f7d2416 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 6 Aug 2025 11:20:17 +0530 Subject: [PATCH 2/2] tests: Add a test for screenshot ref commit behaviour --- tests/Makefile.am.inc | 3 ++ tests/meson.build | 3 ++ tests/org.flatpak_builder.gui.desktop | 9 +++++ tests/org.flatpak_builder.gui.json | 41 ++++++++++++++++++++++ tests/org.flatpak_builder.gui.metainfo.xml | 35 ++++++++++++++++++ tests/test-builder.sh | 16 ++++++++- 6 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 tests/org.flatpak_builder.gui.desktop create mode 100644 tests/org.flatpak_builder.gui.json create mode 100644 tests/org.flatpak_builder.gui.metainfo.xml diff --git a/tests/Makefile.am.inc b/tests/Makefile.am.inc index 2b778b61..ff10308d 100644 --- a/tests/Makefile.am.inc +++ b/tests/Makefile.am.inc @@ -58,6 +58,9 @@ dist_installed_test_data = \ tests/org.test.Deprecated.SHA1.file.yaml \ tests/hello.sh \ tests/hello.tar.xz \ + tests/org.flatpak_builder.gui.desktop \ + tests/org.flatpak_builder.gui.json \ + tests/org.flatpak_builder.gui.metainfo.xml \ $(NULL) installed_test_keyringdir = $(installed_testdir)/test-keyring diff --git a/tests/meson.build b/tests/meson.build index c324bf60..5752ef58 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -105,6 +105,9 @@ if get_option('installed_tests') 'test-runtime.json', 'test.json', 'test.yaml', + 'tests/org.flatpak_builder.gui.desktop', + 'tests/org.flatpak_builder.gui.json', + 'tests/org.flatpak_builder.gui.metainfo.xml', install_dir: installed_testdir, install_mode: 'rw-r--r--', diff --git a/tests/org.flatpak_builder.gui.desktop b/tests/org.flatpak_builder.gui.desktop new file mode 100644 index 00000000..66c81710 --- /dev/null +++ b/tests/org.flatpak_builder.gui.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=Example +GenericName=Example +Comment=Example +Exec=hello %U +Icon=org.flatpak_builder.gui +Type=Application +Categories=Network; +Version=1.1 diff --git a/tests/org.flatpak_builder.gui.json b/tests/org.flatpak_builder.gui.json new file mode 100644 index 00000000..723d2c67 --- /dev/null +++ b/tests/org.flatpak_builder.gui.json @@ -0,0 +1,41 @@ +{ + "id": "org.flatpak_builder.gui", + "runtime": "org.test.Platform", + "sdk": "org.test.Sdk", + "command": "hello", + "modules": [ + { + "name": "hello_gui", + "buildsystem": "simple", + "build-commands": [ + "mkdir -p ${FLATPAK_DEST}/bin ${FLATPAK_DEST}/share/metainfo ${FLATPAK_DEST}/share/applications", + "mkdir -p ${FLATPAK_DEST}/share/icons/hicolor/64x64/apps", + "cp -vf hello.sh ${FLATPAK_DEST}/bin/hello", + "cp -vf ${FLATPAK_ID}.metainfo.xml ${FLATPAK_DEST}/share/metainfo/${FLATPAK_ID}.metainfo.xml", + "cp -vf ${FLATPAK_ID}.desktop ${FLATPAK_DEST}/share/applications/${FLATPAK_ID}.desktop", + "cp -vf org.test.Hello.png ${FLATPAK_DEST}/share/icons/hicolor/64x64/apps/${FLATPAK_ID}.png" + ], + "sources": [ + { + "type": "script", + "dest-filename": "hello.sh", + "commands": [ + "echo \"Hello world, from a sandbox\"" + ] + }, + { + "type": "file", + "path": "org.flatpak_builder.gui.desktop" + }, + { + "type": "file", + "path": "org.flatpak_builder.gui.metainfo.xml" + }, + { + "type": "file", + "path": "org.test.Hello.png" + } + ] + } + ] +} diff --git a/tests/org.flatpak_builder.gui.metainfo.xml b/tests/org.flatpak_builder.gui.metainfo.xml new file mode 100644 index 00000000..abfc30aa --- /dev/null +++ b/tests/org.flatpak_builder.gui.metainfo.xml @@ -0,0 +1,35 @@ + + + org.flatpak_builder.gui + org.flatpak_builder.gui.desktop + CC0-1.0 + GPL-2.0+ + org.flatpak_builder.gui + Flatpak + Foo foo foo foo + https://flatpak.org + +

An example desktop application

+
+ + + + An example screenshot + https://raw.githubusercontent.com/flatpak/flatpak.github.io/0b56895e271bbcc7f86f9570933a96adff99e110/source/img/endless-apps.original.png + + + An example screenshot + https://docs.flathub.org/img/card.png + + + https://flatpak.org + + + + +
diff --git a/tests/test-builder.sh b/tests/test-builder.sh index cd9d8ba0..c503b370 100755 --- a/tests/test-builder.sh +++ b/tests/test-builder.sh @@ -23,7 +23,7 @@ set -euo pipefail skip_without_fuse -echo "1..7" +echo "1..8" setup_repo install_repo @@ -49,6 +49,10 @@ cp $(dirname $0)/Hello-desktop.appdata.xml . cp $(dirname $0)/org.test.Hello.desktop . cp $(dirname $0)/org.test.Hello.xml . cp $(dirname $0)/org.test.Hello.appdata.xml . +cp $(dirname $0)/org.flatpak_builder.gui.desktop . +cp $(dirname $0)/org.flatpak_builder.gui.json . +cp $(dirname $0)/org.flatpak_builder.gui.metainfo.xml . +cp $(dirname $0)/org.test.Hello.png . mkdir include1 cp $(dirname $0)/module1.json include1/ cp $(dirname $0)/module1.yaml include1/ @@ -127,3 +131,13 @@ ${FLATPAK_BUILDER} $FL_GPGARGS --repo=$REPO --force-clean runtimedir \ test-runtime.json >&2 echo "ok runtime build cleanup with build-args" + +# test screenshot ref commit +${FLATPAK_BUILDER} --repo=$REPO/repo_sc --force-clean builddir_sc \ + --mirror-screenshots-url=https://example.org/media \ + org.flatpak_builder.gui.json >&2 +ostree --repo=$REPO/repo_sc refs|grep -Eq "^screenshots/$(flatpak --default-arch)$" +ostree checkout --repo=$REPO/repo_sc -U screenshots/$(flatpak --default-arch) outdir_sc +find outdir_sc -path "*/screenshots/image-1_orig.png" -type f | grep -q . + +echo "ok screenshot ref commit"