From 6f5e3b395f870e90ae724260c9e3af0bf262ac07 Mon Sep 17 00:00:00 2001 From: deepend Date: Thu, 10 Sep 2026 19:55:33 -0600 Subject: [PATCH] fix failed CI builds --- .github/workflows/appimage-build.yml | 4 +- .github/workflows/windows-build.yml | 25 ++++++++++ src/fe-gtk/emoji-font.c | 4 +- src/fe-gtk/tests/test-emoji-font.c | 70 ++++++++++++++++++++++++---- src/fe-gtk/tests/test-emoji-ui.c | 17 +++++++ win32/copy/copy.vcxproj | 9 ++-- win32/installer/zoitechat.iss.tt | 3 ++ win32/zoitechat.props | 2 +- 8 files changed, 116 insertions(+), 18 deletions(-) diff --git a/.github/workflows/appimage-build.yml b/.github/workflows/appimage-build.yml index 81233fdb..ca872681 100644 --- a/.github/workflows/appimage-build.yml +++ b/.github/workflows/appimage-build.yml @@ -30,7 +30,7 @@ jobs: gettext \ libcanberra-dev libglib2.0-dev \ libarchive-dev \ - libgtk-3-dev libfontconfig1-dev libpango1.0-dev xvfb xauth \ + libgtk-3-dev libfontconfig1-dev libpango1.0-dev xvfb xauth dbus-daemon at-spi2-core \ libwayland-client0 libwayland-cursor0 libwayland-egl1 \ libxkbcommon0 \ libgtk-3-bin libglib2.0-bin shared-mime-info gsettings-desktop-schemas \ @@ -57,7 +57,7 @@ jobs: ninja -C build - name: Test emoji catalog, font coverage and picker - run: xvfb-run -a meson test -C build --print-errorlogs "Emoji Data Tests" "Emoji Font Tests" "Emoji UI Tests" + run: xvfb-run -a dbus-run-session -- meson test -C build --print-errorlogs "Emoji Data Tests" "Emoji Font Tests" "Emoji UI Tests" - name: Install to AppDir run: | diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index b9e5f092..97184da5 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -69,6 +69,30 @@ jobs: Download-WithRetry -Url https://github.com/ZoiteChat/gvsbuild/releases/download/zoitechat-2.20.0-alpha.1/GTK3_Gvsbuild_zoitechat-2.20.0-alpha.1_x64.zip -OutFile deps\gtk-${{ matrix.arch }}.zip Expand-Archive -LiteralPath deps\gtk-${{ matrix.arch }}.zip -DestinationPath C:\gtk-build\gtk\x64\release -Force + # The GTK3 archive omits librsvg. Add only its renderer, loader and + # license from the companion release, keeping the GTK3 DLLs intact. + Download-WithRetry -Url https://github.com/ZoiteChat/gvsbuild/releases/download/zoitechat-2.20.0-alpha.1/GTK4_Gvsbuild_zoitechat-2.20.0-alpha.1_x64.zip -OutFile deps\svg-runtime.zip + if ((Get-FileHash deps\svg-runtime.zip -Algorithm SHA256).Hash -ne 'fb657f9ebae3a6807defb15e66091d643a703ee66cb37488e3e11e5646f45adb') { + throw 'Unexpected SVG runtime archive checksum' + } + $svgArchive = [System.IO.Compression.ZipFile]::OpenRead((Resolve-Path deps\svg-runtime.zip)) + try { + foreach ($name in @('bin/rsvg-2-2.dll', 'lib/gdk-pixbuf-2.0/2.10.0/loaders/pixbufloader_svg.dll', 'share/doc/librsvg/COPYING.LIB')) { + $entry = $svgArchive.GetEntry($name) + if ($null -eq $entry) { throw "Missing SVG runtime file: $name" } + $destination = Join-Path 'C:\gtk-build\gtk\x64\release' $name + New-Item -ItemType Directory -Path (Split-Path $destination) -Force | Out-Null + [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $destination, $true) + } + } + finally { $svgArchive.Dispose() } + # This loads the module now, catching missing DLLs before the build. + & C:\gtk-build\gtk\x64\release\bin\gdk-pixbuf-query-loaders.exe --update-cache + if ($LASTEXITCODE -ne 0) { throw 'Could not generate the pixbuf loader cache' } + if (-not (Select-String -LiteralPath 'C:\gtk-build\gtk\x64\release\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache' -SimpleMatch '"svg"')) { + throw 'SVG loader could not be loaded with the GTK3 runtime' + } + Download-WithRetry -Url https://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-hicolor-icon-theme-0.18-1-any.pkg.tar.zst -OutFile deps\hicolor-icon-theme.pkg.tar.zst python -c "import tarfile,zstandard,pathlib;archive=pathlib.Path(r'deps\\hicolor-icon-theme.pkg.tar.zst');target=pathlib.Path(r'C:\\gtk-build\\gtk\\x64\\release');dctx=zstandard.ZstdDecompressor();f=archive.open('rb');reader=dctx.stream_reader(f);tf=tarfile.open(fileobj=reader,mode='r|');[tf.extract(m,path=target) for m in tf if m.name.startswith('mingw64/share/icons/hicolor/')];tf.close();reader.close();f.close()" @@ -179,6 +203,7 @@ jobs: run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" set "PATH=%CD%\..\zoitechat-build\x64\rel;%PATH%" + set "GDK_PIXBUF_MODULE_FILE=%CD%\..\zoitechat-build\x64\rel\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache" set "ZOITECHAT_EMOJI_FONT=%CD%\..\zoitechat-build\x64\rel\share\fonts\zoitechat\NotoColorEmoji.ttf" fc /b data\fonts\NotoColorEmoji.ttf "%ZOITECHAT_EMOJI_FONT%" if errorlevel 1 exit /b 1 diff --git a/src/fe-gtk/emoji-font.c b/src/fe-gtk/emoji-font.c index 73786d4f..cad54193 100644 --- a/src/fe-gtk/emoji-font.c +++ b/src/fe-gtk/emoji-font.c @@ -78,7 +78,9 @@ emoji_font_get_map (void) "" ZOITECHAT_EMOJI_FAMILY "" "emoji" - "" + /* System rules may already have prepended older emoji families. + * Put our bundled family before those, not just before 'emoji'. */ + "" ZOITECHAT_EMOJI_FAMILY "" "", escaped); registered = FcConfigParseAndLoadFromMemory (config, (const FcChar8 *) rules, FcTrue) && diff --git a/src/fe-gtk/tests/test-emoji-font.c b/src/fe-gtk/tests/test-emoji-font.c index ddf4a8c0..cd007831 100644 --- a/src/fe-gtk/tests/test-emoji-font.c +++ b/src/fe-gtk/tests/test-emoji-font.c @@ -3,6 +3,52 @@ #include "../emoji-font.h" #include "../../common/emoji-data.h" #include +#include + +static GHashTable *font_checksums; +static char *bundled_checksum; + +static const char * +font_checksum (const char *path) +{ + const char *cached = g_hash_table_lookup (font_checksums, path); + char *contents, *checksum; + gsize length; + + if (cached) + return cached; + g_assert_true (g_file_get_contents (path, &contents, &length, NULL)); + checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA256, + (const guchar *) contents, length); + g_free (contents); + g_hash_table_insert (font_checksums, g_strdup (path), checksum); + return checksum; +} + +static void +assert_bundled_font (PangoFont *font, gboolean expected) +{ + FcPattern *pattern; + FcChar8 *path; + const char *checksum; + + /* Pango can describe a face by its embedded name rather than its + * Fontconfig alias. Verify the resolved file's bytes, not that name. + * Cache by filename so catalog coverage does not reread the font for + * every glyph. An older system Noto must still fail this assertion. */ + g_assert_true (PANGO_IS_FC_FONT (font)); +#if PANGO_VERSION_CHECK(1, 48, 0) + pattern = pango_fc_font_get_pattern (PANGO_FC_FONT (font)); +#else + pattern = PANGO_FC_FONT (font)->font_pattern; +#endif + g_assert_cmpint (FcPatternGetString (pattern, FC_FILE, 0, &path), ==, FcResultMatch); + checksum = font_checksum ((const char *) path); + if (expected) + g_assert_cmpstr (checksum, ==, bundled_checksum); + else + g_assert_cmpstr (checksum, !=, bundled_checksum); +} static void test_font_catalog (void) @@ -34,9 +80,7 @@ test_font_catalog (void) PangoLayoutRun *run = pango_layout_iter_get_run_readonly (iter); if (run) { - PangoFontDescription *actual = pango_font_describe (run->item->analysis.font); - g_assert_cmpstr (pango_font_description_get_family (actual), ==, ZOITECHAT_EMOJI_FAMILY); - pango_font_description_free (actual); + assert_bundled_font (run->item->analysis.font, TRUE); } } while (pango_layout_iter_next_run (iter)); pango_layout_iter_free (iter); @@ -68,9 +112,7 @@ test_plain_text_font (void) PangoLayoutRun *run = pango_layout_iter_get_run_readonly (iter); if (run) { - PangoFontDescription *actual = pango_font_describe (run->item->analysis.font); - g_assert_cmpstr (pango_font_description_get_family (actual), !=, ZOITECHAT_EMOJI_FAMILY); - pango_font_description_free (actual); + assert_bundled_font (run->item->analysis.font, FALSE); } } while (pango_layout_iter_next_run (iter)); pango_layout_iter_free (iter); @@ -101,9 +143,7 @@ test_implicit_emoji_font (void) PangoLayoutRun *run = pango_layout_iter_get_run_readonly (iter); if (run) { - PangoFontDescription *actual = pango_font_describe (run->item->analysis.font); - g_assert_cmpstr (pango_font_description_get_family (actual), ==, ZOITECHAT_EMOJI_FAMILY); - pango_font_description_free (actual); + assert_bundled_font (run->item->analysis.font, TRUE); } } while (pango_layout_iter_next_run (iter)); pango_layout_iter_free (iter); @@ -116,9 +156,19 @@ test_implicit_emoji_font (void) int main (int argc, char **argv) { + const char *path; + int result; + g_test_init (&argc, &argv, NULL); + path = g_getenv ("ZOITECHAT_EMOJI_FONT"); + g_assert_nonnull (path); + font_checksums = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + bundled_checksum = g_strdup (font_checksum (path)); g_test_add_func ("/emoji-font/catalog", test_font_catalog); g_test_add_func ("/emoji-font/plain-text", test_plain_text_font); g_test_add_func ("/emoji-font/implicit-emoji", test_implicit_emoji_font); - return g_test_run (); + result = g_test_run (); + g_free (bundled_checksum); + g_hash_table_destroy (font_checksums); + return result; } diff --git a/src/fe-gtk/tests/test-emoji-ui.c b/src/fe-gtk/tests/test-emoji-ui.c index b2be3897..128c6717 100644 --- a/src/fe-gtk/tests/test-emoji-ui.c +++ b/src/fe-gtk/tests/test-emoji-ui.c @@ -12,6 +12,22 @@ struct zoitechatprefs prefs; static char *config_dir; +static void +test_theme_svg_loader (void) +{ + GError *error = NULL; + GdkPixbuf *pixbuf; + + /* Exercise the theme asset that failed in the packaged Windows runtime. */ + pixbuf = gdk_pixbuf_new_from_resource ( + "/org/gtk/libgtk/theme/Adwaita/assets/bullet-symbolic.svg", &error); + g_assert_no_error (error); + g_assert_nonnull (pixbuf); + g_assert_cmpint (gdk_pixbuf_get_width (pixbuf), >, 0); + g_assert_cmpint (gdk_pixbuf_get_height (pixbuf), >, 0); + g_object_unref (pixbuf); +} + char *get_xdir (void) { return config_dir; } PreferencesPersistenceResult preferences_persistence_save_all (void) { @@ -125,6 +141,7 @@ main (int argc, char **argv) g_object_set (gtk_settings_get_default (), "gtk-enable-animations", FALSE, NULL); config_dir = g_dir_make_tmp ("zoitechat-emoji-tests-XXXXXX", NULL); g_assert_nonnull (config_dir); + g_test_add_func ("/emoji-ui/theme-svg-loader", test_theme_svg_loader); g_test_add ("/emoji-ui/search-insertion", PickerFixture, NULL, fixture_setup, test_search_insertion, fixture_teardown); g_test_add ("/emoji-ui/read-only", PickerFixture, NULL, fixture_setup, test_read_only, fixture_teardown); g_test_add ("/emoji-ui/sequence-limit", PickerFixture, NULL, fixture_setup, test_sequence_limit, fixture_teardown); diff --git a/win32/copy/copy.vcxproj b/win32/copy/copy.vcxproj index 31938cd0..e5f3730b 100644 --- a/win32/copy/copy.vcxproj +++ b/win32/copy/copy.vcxproj @@ -37,6 +37,7 @@ + @@ -78,8 +79,8 @@ - - + + @@ -97,8 +98,8 @@ - - + + diff --git a/win32/installer/zoitechat.iss.tt b/win32/installer/zoitechat.iss.tt index 2a1ab67d..09339a6d 100644 --- a/win32/installer/zoitechat.iss.tt +++ b/win32/installer/zoitechat.iss.tt @@ -106,6 +106,8 @@ Source: "share\xml\*"; DestDir: "{app}\share\xml"; Flags: ignoreversion createal Source: "share\doc\zoitechat\*"; DestDir: "{app}\share\doc\zoitechat"; Flags: ignoreversion createallsubdirs recursesubdirs; Components: libs Source: "share\fonts\zoitechat\*"; DestDir: "{app}\share\fonts\zoitechat"; Flags: ignoreversion createallsubdirs recursesubdirs; Components: libs Source: "share\doc\WinSparkle\*"; DestDir: "{app}\share\doc\WinSparkle"; Flags: ignoreversion createallsubdirs recursesubdirs; Components: libs +Source: "share\doc\librsvg\*"; DestDir: "{app}\share\doc\librsvg"; Flags: ignoreversion createallsubdirs recursesubdirs; Components: libs +Source: "lib\gdk-pixbuf-2.0\*"; DestDir: "{app}\lib\gdk-pixbuf-2.0"; Flags: ignoreversion createallsubdirs recursesubdirs; Components: libs Source: "share\themes\MS-Windows\*"; DestDir: "{app}\share\themes\MS-Windows"; Flags: ignoreversion createallsubdirs recursesubdirs skipifsourcedoesntexist; Components: libs Source: "share\glib-2.0\schemas\*"; DestDir: "{app}\share\glib-2.0\schemas"; Flags: ignoreversion createallsubdirs recursesubdirs skipifsourcedoesntexist; Components: libs Source: "share\icons\hicolor\*"; DestDir: "{app}\share\icons\hicolor"; Flags: ignoreversion createallsubdirs recursesubdirs skipifsourcedoesntexist; Components: libs @@ -118,6 +120,7 @@ Source: "freetype-6.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: li Source: "fribidi-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "fontconfig-1.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "gdk_pixbuf-2.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs +Source: "rsvg-2-2.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "gdk-3-vs17.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "epoxy-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "gio-2.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs diff --git a/win32/zoitechat.props b/win32/zoitechat.props index 5513e3c4..f393022d 100644 --- a/win32/zoitechat.props +++ b/win32/zoitechat.props @@ -75,7 +75,7 @@ true $(DepsRoot)\include\gtk-3.0;$(DepsRoot)\lib\gtk-3.0\include - $(DepsRoot)\include\atk-1.0;$(DepsRoot)\include\cairo;$(DepsRoot)\include\pango-1.0;$(DepsRoot)\include\gdk-pixbuf-2.0;$(DepsRoot)\include\harfbuzz + $(DepsRoot)\include\atk-1.0;$(DepsRoot)\include\cairo;$(DepsRoot)\include\pango-1.0;$(DepsRoot)\include\gdk-pixbuf-2.0;$(DepsRoot)\include\harfbuzz;$(DepsRoot)\include\freetype2 $(Gtk3);$(GtkCommon) ssleay32.lib