From cdaa56d1abfa1013de51eb40a0071bf1d84abc24 Mon Sep 17 00:00:00 2001 From: Pascal Garber Date: Fri, 11 Sep 2026 08:58:03 +0200 Subject: [PATCH 1/3] fix: publish in topological order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v4.9.0 published all 716 `@girs/*` packages in `readdir` order. Measured afterwards from the registry's own `time` maps: the sweep ran from 22:15:33Z to 00:23:15Z, and **508 of the 716 packages were published before something they declare a dependency on existed**. `@girs/adw-1` went out first and names fifteen siblings; `@girs/pango-1.0` appeared 96 minutes later. gjsify's e2e legs went red twice inside that window with npm error notarget No matching version found for @girs/pango-1.0@^4.9.0 an error naming neither the package the consumer asked for nor the repository the cause lives in. Two halves, because order alone stops being right the first time someone changes how packages are collected: - `planPublishOrder` condenses the graph into its strongly connected components (Tarjan, iterative) and publishes the components in an order where nothing precedes what it needs. Deterministic, so a resumed release republishes in the order it started in. - after every group, the closure of its members is resolved against the REGISTRY β€” not against our own bookkeeping β€” with the edges inside the group exempt, and a surviving gap fails the run naming package, dependency and range. The graph is not a DAG. Tarjan finds one non-trivial component and it has six members: cairo-1.0, gio-2.0, gjs, glib-2.0, gmodule-2.0, gobject-2.0. No order can complete a cycle member's closure at its own publish instant, so the unit of both halves is the GROUP. A per-package gate would be red on a correct release, which is how a gate gets switched off. The components are computed, never enumerated: the first count of the damage exempted glib/gobject by hand and was five packages wrong. Also here, found while making the above testable: - `--verify-only` asks the same question of the registry at any time. - a real `npm install` of the published set into an empty directory ends the sweep β€” the only check that also proves the tarballs exist, which `@girs/sdk-gnome-master@4.7.0` needed and nothing had. - `--root` resolves against the working directory instead of against this file's own repository, which is what made an end-to-end test possible. - a scan that finds no package.json is an error, not a silent success. - `npm publish`'s stdout is drained; an undrained pipe blocks the child at 64 KB and reports as a timeout. - `--provenance` only against the public registry, where it exists. Controls, because a gate that has never been red is not a gate. `publish-plan.test.ts` replays the recorded v4.9.0 graph through the real gate: 508 red in the order it went out, 0 in the planned order, and the cycle members exempt in both. `test/e2e.mjs` runs the publisher against a throwaway Verdaccio; with the gate stubbed out both negative arms go green, and with the plan replaced by manifest order the run dies on the first group. Claude-Session: https://claude.ai/code/session_01N4yEeHoGMC4pvbkqxMsYfj --- .../release-script/fixtures/girs-4.9.0.json | 11225 ++++++++++++++++ .github/release-script/package-lock.json | 27 +- .github/release-script/package.json | 6 + .github/release-script/src/index.ts | 439 +- .../release-script/src/publish-plan.test.ts | 276 + .github/release-script/src/publish-plan.ts | 310 + .github/release-script/test/e2e.mjs | 318 + .github/release-script/tsconfig.json | 1 + .github/workflows/release-script.yml | 63 + .github/workflows/release.yml | 14 +- .github/workflows/sdk-types.yml | 9 +- 11 files changed, 12640 insertions(+), 48 deletions(-) create mode 100644 .github/release-script/fixtures/girs-4.9.0.json create mode 100644 .github/release-script/src/publish-plan.test.ts create mode 100644 .github/release-script/src/publish-plan.ts create mode 100644 .github/release-script/test/e2e.mjs create mode 100644 .github/workflows/release-script.yml diff --git a/.github/release-script/fixtures/girs-4.9.0.json b/.github/release-script/fixtures/girs-4.9.0.json new file mode 100644 index 0000000000..b8ff693fa3 --- /dev/null +++ b/.github/release-script/fixtures/girs-4.9.0.json @@ -0,0 +1,11225 @@ +{ + "$comment": "Recorded state of the v4.9.0 @girs release. See publish-plan.test.ts.", + "recorded": "2026-09-11", + "release": "4.9.0", + "source": "the 716 package.json files of gjsify/types@9ab5e6437 (dependency edges) and registry.npmjs.org packument time maps (publish instants)", + "packages": { + "abi-3.0": { + "published": "2026-09-10T22:15:33.008Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gsf-1", + "gtk-3.0", + "harfbuzz-0.0", + "libxml2-2.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "accounts-1.0": { + "published": "2026-09-10T22:15:43.207Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "accountsservice-1.0": { + "published": "2026-09-10T22:18:34.460Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "adw-1": { + "published": "2026-09-10T22:17:43.206Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "ags-6.0": { + "published": "2026-09-10T22:17:56.777Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "ags-8.0": { + "published": "2026-09-10T22:20:35.713Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "agsaudio-6.0": { + "published": "2026-09-10T22:16:36.244Z", + "dependencies": [ + "ags-6.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "agsaudio-8.0": { + "published": "2026-09-10T22:16:46.897Z", + "dependencies": [ + "ags-8.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "agsgui-6.0": { + "published": "2026-09-10T22:16:57.478Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "libxml2-2.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "agsgui-8.0": { + "published": "2026-09-10T22:17:08.394Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "libxml2-2.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "amtk-4": { + "published": "2026-09-10T22:20:28.950Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "amtk-5": { + "published": "2026-09-10T22:17:29.044Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "anacondawidgets-3.4": { + "published": "2026-09-10T22:18:55.683Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xkl-1.0", + "xlib-2.0" + ] + }, + "anjuta-3.0": { + "published": "2026-09-10T22:17:49.708Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gdl-3", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "anthy-9000": { + "published": "2026-09-10T22:18:00.274Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "appindicator3-0.1": { + "published": "2026-09-10T22:18:10.617Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "appstream-1.0": { + "published": "2026-09-10T22:19:17.272Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "appstreambuilder-1.0": { + "published": "2026-09-10T22:18:31.209Z", + "dependencies": [ + "appstreamglib-1.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "appstreamcompose-1.0": { + "published": "2026-09-10T22:18:41.729Z", + "dependencies": [ + "appstream-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "appstreamglib-1.0": { + "published": "2026-09-10T22:18:52.312Z", + "dependencies": [ + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "arrow-1.0": { + "published": "2026-09-10T22:19:03.262Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "arrow-23.0": { + "published": "2026-09-10T22:19:48.014Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "arrowcuda-1.0": { + "published": "2026-09-10T22:19:23.877Z", + "dependencies": [ + "arrow-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "arrowdataset-1.0": { + "published": "2026-09-10T22:19:34.517Z", + "dependencies": [ + "arrow-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "arrowdataset-23.0": { + "published": "2026-09-10T22:20:41.891Z", + "dependencies": [ + "arrow-23.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "arrowflight-1.0": { + "published": "2026-09-10T22:19:56.111Z", + "dependencies": [ + "arrow-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "arrowflight-23.0": { + "published": "2026-09-10T22:21:43.615Z", + "dependencies": [ + "arrow-23.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "atk-1.0": { + "published": "2026-09-10T22:20:16.427Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "atrildocument-1.5.0": { + "published": "2026-09-10T22:20:26.788Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "atrilview-1.5.0": { + "published": "2026-09-10T22:20:37.437Z", + "dependencies": [ + "atk-1.0", + "atrildocument-1.5.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "atspi-2.0": { + "published": "2026-09-10T22:20:47.878Z", + "dependencies": [ + "dbus-1.0", + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "avahi-0.6": { + "published": "2026-09-10T22:20:58.686Z", + "dependencies": [ + "avahicore-0.6", + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "avahicore-0.6": { + "published": "2026-09-10T22:21:09.163Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "ayatanaappindicator-0.1": { + "published": "2026-09-10T22:22:36.990Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "ayatanaappindicator3-0.1": { + "published": "2026-09-10T22:23:07.677Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "ayatanaido3-0.4": { + "published": "2026-09-10T22:21:40.940Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "babl-0.1": { + "published": "2026-09-10T22:25:00.367Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "bamf-3": { + "published": "2026-09-10T22:22:57.735Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "blockdev-3.0": { + "published": "2026-09-10T22:22:12.607Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "braseroburn-3.1": { + "published": "2026-09-10T22:22:22.802Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "braseromedia-3.1": { + "published": "2026-09-10T22:22:33.120Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "budgie-1.0": { + "published": "2026-09-10T22:23:39.715Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "girepository-3.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "peas-1.0", + "xlib-2.0" + ] + }, + "budgie-3.0": { + "published": "2026-09-10T22:22:54.600Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "peas-2", + "xlib-2.0" + ] + }, + "budgieraven-1.0": { + "published": "2026-09-10T22:24:41.883Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "girepository-3.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "peas-1.0", + "xlib-2.0" + ] + }, + "budgieraven-3.0": { + "published": "2026-09-10T22:24:51.347Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "peas-2", + "xlib-2.0" + ] + }, + "builder-1.0": { + "published": "2026-09-10T22:23:25.664Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "dazzle-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "girepository-3.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "gtksource-3.0", + "harfbuzz-0.0", + "ide-1.0", + "json-1.0", + "pango-1.0", + "peas-1.0", + "template-1.0", + "xlib-2.0" + ] + }, + "bump-0.1": { + "published": "2026-09-10T22:26:13.356Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "cairo-1.0": { + "published": "2026-09-10T22:25:54.423Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "caja-2.0": { + "published": "2026-09-10T22:23:56.773Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "cally-1.0": { + "published": "2026-09-10T22:25:02.683Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-1.0", + "cogl-1.0", + "coglpango-1.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cally-10": { + "published": "2026-09-10T22:26:24.238Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-10", + "cogl-10", + "coglpango-10", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cally-11": { + "published": "2026-09-10T22:24:27.630Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-11", + "cogl-11", + "coglpango-11", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cally-12": { + "published": "2026-09-10T22:24:38.019Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-12", + "cogl-12", + "coglpango-12", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cally-13": { + "published": "2026-09-10T22:26:03.850Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-13", + "cogl-13", + "coglpango-13", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "mtk-13", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cally-14": { + "published": "2026-09-10T22:29:08.189Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-14", + "cogl-14", + "coglpango-14", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-14", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "cally-15": { + "published": "2026-09-10T22:25:08.724Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-15", + "cogl-15", + "coglpango-15", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-15", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "cally-3": { + "published": "2026-09-10T22:25:19.141Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-3", + "cogl-3", + "coglpango-3", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cally-4": { + "published": "2026-09-10T22:26:25.136Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-4", + "cogl-4", + "coglpango-4", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cally-5": { + "published": "2026-09-10T22:26:35.056Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-5", + "cogl-5", + "coglpango-5", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cally-6": { + "published": "2026-09-10T22:25:49.858Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-6", + "cogl-6", + "coglpango-6", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cally-7": { + "published": "2026-09-10T22:26:00.632Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-7", + "cogl-7", + "coglpango-7", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cally-8": { + "published": "2026-09-10T22:32:22.467Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-8", + "cogl-8", + "coglpango-8", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cally-9": { + "published": "2026-09-10T22:26:21.246Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-9", + "cogl-9", + "coglpango-9", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cambalacheprivate-3.0": { + "published": "2026-09-10T22:26:31.630Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "cambalacheprivate-4.0": { + "published": "2026-09-10T22:27:37.168Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "camel-1.2": { + "published": "2026-09-10T22:29:00.335Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxml2-2.0" + ] + }, + "caribou-1.0": { + "published": "2026-09-10T22:27:58.739Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "casilda-0.1": { + "published": "2026-09-10T22:29:21.010Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "casilda-1.0": { + "published": "2026-09-10T22:27:23.959Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cdesktopenums-3.0": { + "published": "2026-09-10T22:28:30.537Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "champlain-0.12": { + "published": "2026-09-10T22:28:41.283Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-1.0", + "cogl-1.0", + "coglpango-1.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cheese-3.0": { + "published": "2026-09-10T22:28:52.661Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-1.0", + "cogl-1.0", + "coglpango-1.0", + "freetype2-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cinnamondesktop-3.0": { + "published": "2026-09-10T22:28:08.055Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cdesktopenums-3.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "clapper-0.0": { + "published": "2026-09-10T22:28:18.491Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstpbutils-1.0", + "gsttag-1.0", + "gstvideo-1.0" + ] + }, + "clappergtk-0.0": { + "published": "2026-09-10T22:29:24.487Z", + "dependencies": [ + "cairo-1.0", + "clapper-0.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstpbutils-1.0", + "gsttag-1.0", + "gstvideo-1.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cloudproviders-0.3": { + "published": "2026-09-10T22:28:40.011Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "clutter-1.0": { + "published": "2026-09-10T22:28:50.813Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-1.0", + "coglpango-1.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "clutter-10": { + "published": "2026-09-10T22:31:09.633Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-10", + "coglpango-10", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "clutter-11": { + "published": "2026-09-10T22:31:19.732Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-11", + "coglpango-11", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "clutter-12": { + "published": "2026-09-10T22:30:17.613Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-12", + "coglpango-12", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "clutter-13": { + "published": "2026-09-10T22:31:40.089Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-13", + "coglpango-13", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "mtk-13", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "clutter-14": { + "published": "2026-09-10T22:31:49.950Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-14", + "coglpango-14", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-14", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "clutter-15": { + "published": "2026-09-10T22:29:53.465Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-15", + "coglpango-15", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-15", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "clutter-16": { + "published": "2026-09-10T22:31:20.180Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-16", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-16", + "pango-1.0", + "xlib-2.0" + ] + }, + "clutter-17": { + "published": "2026-09-10T22:31:11.184Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-17", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-17", + "pango-1.0" + ] + }, + "clutter-18": { + "published": "2026-09-10T22:30:24.934Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-18", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-18", + "pango-1.0" + ] + }, + "clutter-3": { + "published": "2026-09-10T22:31:31.016Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-3", + "coglpango-3", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "clutter-4": { + "published": "2026-09-10T22:30:45.758Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-4", + "coglpango-4", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "clutter-5": { + "published": "2026-09-10T22:30:56.315Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-5", + "coglpango-5", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "clutter-51": { + "published": "2026-09-10T22:31:06.912Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-51", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-51", + "pango-1.0" + ] + }, + "clutter-6": { + "published": "2026-09-10T22:31:17.404Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-6", + "coglpango-6", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "clutter-7": { + "published": "2026-09-10T22:34:06.935Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-7", + "coglpango-7", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "clutter-8": { + "published": "2026-09-10T22:32:34.207Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-8", + "coglpango-8", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "clutter-9": { + "published": "2026-09-10T22:32:44.666Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cogl-9", + "coglpango-9", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cluttergdk-1.0": { + "published": "2026-09-10T22:31:58.549Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-1.0", + "cogl-1.0", + "coglpango-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cluttergst-2.0": { + "published": "2026-09-10T22:32:09.211Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-1.0", + "cogl-1.0", + "coglpango-1.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstvideo-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cluttergst-3.0": { + "published": "2026-09-10T22:33:16.268Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-1.0", + "cogl-1.0", + "coglpango-1.0", + "freetype2-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstpbutils-1.0", + "gstvideo-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "clutterx11-1.0": { + "published": "2026-09-10T22:33:46.434Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-1.0", + "cogl-1.0", + "coglpango-1.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "clutterx11-3": { + "published": "2026-09-10T22:32:40.907Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-3", + "cogl-3", + "coglpango-3", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "clutterx11-4": { + "published": "2026-09-10T22:34:08.096Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-4", + "cogl-4", + "coglpango-4", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "clutterx11-5": { + "published": "2026-09-10T22:33:57.985Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-5", + "cogl-5", + "coglpango-5", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "clutterx11-6": { + "published": "2026-09-10T22:33:46.843Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-6", + "cogl-6", + "coglpango-6", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "clutterx11-7": { + "published": "2026-09-10T22:34:42.573Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-7", + "cogl-7", + "coglpango-7", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "clutterx11-8": { + "published": "2026-09-10T22:36:41.016Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-8", + "cogl-8", + "coglpango-8", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "cmbcatalogutils-3.0": { + "published": "2026-09-10T22:33:42.999Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "cmbcatalogutils-4.0": { + "published": "2026-09-10T22:34:48.362Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "cmenu-3.0": { + "published": "2026-09-10T22:34:59.191Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "cogl-1.0": { + "published": "2026-09-10T22:35:29.322Z", + "dependencies": [ + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0" + ] + }, + "cogl-10": { + "published": "2026-09-10T22:36:32.504Z", + "dependencies": [ + "cairo-1.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "cogl-11": { + "published": "2026-09-10T22:34:34.230Z", + "dependencies": [ + "cairo-1.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "cogl-12": { + "published": "2026-09-10T22:34:44.997Z", + "dependencies": [ + "cairo-1.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "cogl-13": { + "published": "2026-09-10T22:35:49.961Z", + "dependencies": [ + "cairo-1.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "cogl-14": { + "published": "2026-09-10T22:35:05.923Z", + "dependencies": [ + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0", + "mtk-14", + "xlib-2.0" + ] + }, + "cogl-15": { + "published": "2026-09-10T22:38:26.232Z", + "dependencies": [ + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0", + "mtk-15", + "xlib-2.0" + ] + }, + "cogl-16": { + "published": "2026-09-10T22:35:26.586Z", + "dependencies": [ + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0", + "mtk-16", + "xlib-2.0" + ] + }, + "cogl-17": { + "published": "2026-09-10T22:37:13.981Z", + "dependencies": [ + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0", + "mtk-17" + ] + }, + "cogl-18": { + "published": "2026-09-10T22:39:57.200Z", + "dependencies": [ + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0", + "mtk-18" + ] + }, + "cogl-2.0": { + "published": "2026-09-10T22:37:34.889Z", + "dependencies": [ + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0" + ] + }, + "cogl-3": { + "published": "2026-09-10T22:36:08.201Z", + "dependencies": [ + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0" + ] + }, + "cogl-4": { + "published": "2026-09-10T22:38:26.314Z", + "dependencies": [ + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0" + ] + }, + "cogl-5": { + "published": "2026-09-10T22:36:29.549Z", + "dependencies": [ + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0" + ] + }, + "cogl-51": { + "published": "2026-09-10T22:38:16.849Z", + "dependencies": [ + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0", + "mtk-51" + ] + }, + "cogl-6": { + "published": "2026-09-10T22:36:50.615Z", + "dependencies": [ + "cairo-1.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "cogl-7": { + "published": "2026-09-10T22:38:17.092Z", + "dependencies": [ + "cairo-1.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "cogl-8": { + "published": "2026-09-10T22:37:11.402Z", + "dependencies": [ + "cairo-1.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "cogl-9": { + "published": "2026-09-10T22:40:01.512Z", + "dependencies": [ + "cairo-1.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "coglgst-2.0": { + "published": "2026-09-10T22:38:50.504Z", + "dependencies": [ + "cogl-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0" + ] + }, + "coglpango-1.0": { + "published": "2026-09-10T22:38:38.980Z", + "dependencies": [ + "cairo-1.0", + "cogl-1.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "coglpango-10": { + "published": "2026-09-10T22:37:53.229Z", + "dependencies": [ + "cairo-1.0", + "cogl-10", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "coglpango-11": { + "published": "2026-09-10T22:39:02.718Z", + "dependencies": [ + "cairo-1.0", + "cogl-11", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "coglpango-12": { + "published": "2026-09-10T22:39:11.570Z", + "dependencies": [ + "cairo-1.0", + "cogl-12", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "coglpango-13": { + "published": "2026-09-10T22:38:24.689Z", + "dependencies": [ + "cairo-1.0", + "cogl-13", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "coglpango-14": { + "published": "2026-09-10T22:38:35.003Z", + "dependencies": [ + "cairo-1.0", + "cogl-14", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-14", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "coglpango-15": { + "published": "2026-09-10T22:40:54.721Z", + "dependencies": [ + "cairo-1.0", + "cogl-15", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-15", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "coglpango-2.0": { + "published": "2026-09-10T22:41:36.167Z", + "dependencies": [ + "cairo-1.0", + "cogl-2.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "coglpango-3": { + "published": "2026-09-10T22:40:05.411Z", + "dependencies": [ + "cairo-1.0", + "cogl-3", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "coglpango-4": { + "published": "2026-09-10T22:39:15.467Z", + "dependencies": [ + "cairo-1.0", + "cogl-4", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "coglpango-5": { + "published": "2026-09-10T22:40:44.825Z", + "dependencies": [ + "cairo-1.0", + "cogl-5", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "coglpango-6": { + "published": "2026-09-10T22:39:36.997Z", + "dependencies": [ + "cairo-1.0", + "cogl-6", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "coglpango-7": { + "published": "2026-09-10T22:40:44.283Z", + "dependencies": [ + "cairo-1.0", + "cogl-7", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "coglpango-8": { + "published": "2026-09-10T22:40:55.983Z", + "dependencies": [ + "cairo-1.0", + "cogl-8", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "coglpango-9": { + "published": "2026-09-10T22:42:18.193Z", + "dependencies": [ + "cairo-1.0", + "cogl-9", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "colord-1.0": { + "published": "2026-09-10T22:40:20.295Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "colordgtk-1.0": { + "published": "2026-09-10T22:40:31.724Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "colord-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "colorhug-1.0": { + "published": "2026-09-10T22:40:43.873Z", + "dependencies": [ + "colord-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gusb-1.0", + "json-1.0" + ] + }, + "cryptui-0.0": { + "published": "2026-09-10T22:40:55.648Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "cudagst-1.0": { + "published": "2026-09-10T22:42:01.599Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "cvc-1.0": { + "published": "2026-09-10T22:43:27.815Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "dazzle-1.0": { + "published": "2026-09-10T22:42:22.530Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "dbus-1.0": { + "published": "2026-09-10T22:42:12.427Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "dbusglib-1.0": { + "published": "2026-09-10T22:41:48.090Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "dbusmenu-0.4": { + "published": "2026-09-10T22:43:18.505Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "dbusmenugtk-0.4": { + "published": "2026-09-10T22:43:06.114Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "dbusmenu-0.4", + "freetype2-2.0", + "gdk-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "dbusmenugtk3-0.4": { + "published": "2026-09-10T22:43:45.991Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "dbusmenu-0.4", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "dee-1.0": { + "published": "2026-09-10T22:42:30.085Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "devhelp-3.0": { + "published": "2026-09-10T22:42:40.825Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "javascriptcore-4.1", + "pango-1.0", + "soup-3.0", + "webkit2-4.1", + "xlib-2.0" + ] + }, + "deviced-1.0": { + "published": "2026-09-10T22:43:56.751Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "dex-1": { + "published": "2026-09-10T22:43:04.194Z", + "dependencies": [ + "gio-2.0", + "giounix-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "dmap-3.0": { + "published": "2026-09-10T22:43:14.947Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "soup-2.4" + ] + }, + "dmap-4.0": { + "published": "2026-09-10T22:45:53.333Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "soup-3.0" + ] + }, + "easyfc-0.14": { + "published": "2026-09-10T22:43:35.793Z", + "dependencies": [ + "fontconfig-2.0", + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "ebackend-1.2": { + "published": "2026-09-10T22:46:11.005Z", + "dependencies": [ + "camel-1.2", + "edataserver-1.2", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "ebook-1.2": { + "published": "2026-09-10T22:46:16.606Z", + "dependencies": [ + "camel-1.2", + "ebookcontacts-1.2", + "edataserver-1.2", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "ebookcontacts-1.2": { + "published": "2026-09-10T22:47:21.688Z", + "dependencies": [ + "camel-1.2", + "edataserver-1.2", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "ecal-2.0": { + "published": "2026-09-10T22:44:18.597Z", + "dependencies": [ + "camel-1.2", + "edataserver-1.2", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "icalglib-3.0", + "json-1.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "ecalendar-1.2": { + "published": "2026-09-10T22:44:29.135Z", + "dependencies": [ + "camel-1.2", + "edataserver-1.2", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "edatabook-1.2": { + "published": "2026-09-10T22:45:37.776Z", + "dependencies": [ + "camel-1.2", + "ebackend-1.2", + "ebookcontacts-1.2", + "edataserver-1.2", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "edatacal-2.0": { + "published": "2026-09-10T22:44:51.293Z", + "dependencies": [ + "camel-1.2", + "ebackend-1.2", + "ecal-2.0", + "edataserver-1.2", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "icalglib-3.0", + "json-1.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "edataserver-1.2": { + "published": "2026-09-10T22:45:46.064Z", + "dependencies": [ + "camel-1.2", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "edataserverui-1.2": { + "published": "2026-09-10T22:46:14.291Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "camel-1.2", + "ecal-2.0", + "edataserver-1.2", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "icalglib-3.0", + "json-1.0", + "libxml2-2.0", + "pango-1.0", + "soup-3.0", + "xlib-2.0" + ] + }, + "edataserverui4-1.0": { + "published": "2026-09-10T22:48:07.401Z", + "dependencies": [ + "cairo-1.0", + "camel-1.2", + "ecal-2.0", + "edataserver-1.2", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "icalglib-3.0", + "json-1.0", + "libxml2-2.0", + "pango-1.0", + "pangocairo-1.0", + "soup-3.0" + ] + }, + "egg-1.0": { + "published": "2026-09-10T22:48:23.280Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "entangle-0.1": { + "published": "2026-09-10T22:48:04.573Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gexiv2-0.16", + "gio-2.0", + "girepository-3.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "peas-1.0", + "xlib-2.0" + ] + }, + "eog-3.0": { + "published": "2026-09-10T22:48:13.876Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "eom-1.0": { + "published": "2026-09-10T22:46:08.820Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "epc-1.0": { + "published": "2026-09-10T22:46:20.114Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "epcui-1.0": { + "published": "2026-09-10T22:46:30.759Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "epc-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "evincedocument-3.0": { + "published": "2026-09-10T22:46:41.586Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "evinceview-3.0": { + "published": "2026-09-10T22:49:03.783Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "evincedocument-3.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "farstream-0.1": { + "published": "2026-09-10T22:49:15.799Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-0.10", + "libxml2-2.0" + ] + }, + "farstream-0.2": { + "published": "2026-09-10T22:48:12.818Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0" + ] + }, + "fcitx-1.0": { + "published": "2026-09-10T22:47:27.237Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "fcitxg-1.0": { + "published": "2026-09-10T22:47:37.671Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "fep-1.0": { + "published": "2026-09-10T22:48:24.164Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "flatpak-1.0": { + "published": "2026-09-10T22:47:58.834Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "folks-0.6": { + "published": "2026-09-10T22:49:05.392Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "folks-0.7": { + "published": "2026-09-10T22:49:17.121Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "folksdummy-0.6": { + "published": "2026-09-10T22:49:26.610Z", + "dependencies": [ + "folks-0.6", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "folksdummy-0.7": { + "published": "2026-09-10T22:49:36.763Z", + "dependencies": [ + "folks-0.7", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "folkseds-0.6": { + "published": "2026-09-10T22:48:52.001Z", + "dependencies": [ + "camel-1.2", + "ebookcontacts-1.2", + "edataserver-1.2", + "folks-0.6", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "folkseds-0.7": { + "published": "2026-09-10T22:49:02.314Z", + "dependencies": [ + "camel-1.2", + "ebookcontacts-1.2", + "edataserver-1.2", + "folks-0.7", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "libxml2-2.0", + "soup-3.0" + ] + }, + "folkslibsocialweb-0.6": { + "published": "2026-09-10T22:50:07.795Z", + "dependencies": [ + "folks-0.6", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "socialwebclient-0.25" + ] + }, + "folkstelepathy-0.6": { + "published": "2026-09-10T22:50:19.492Z", + "dependencies": [ + "folks-0.6", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "telepathyglib-0.12" + ] + }, + "folkstelepathy-0.7": { + "published": "2026-09-10T22:49:33.430Z", + "dependencies": [ + "folks-0.7", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "telepathyglib-0.12" + ] + }, + "fontconfig-2.0": { + "published": "2026-09-10T22:50:40.327Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "foundry-1": { + "published": "2026-09-10T22:49:54.738Z", + "dependencies": [ + "dex-1", + "gio-2.0", + "giounix-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "peas-2" + ] + }, + "foundryadw-1": { + "published": "2026-09-10T22:50:05.505Z", + "dependencies": [ + "adw-1", + "cairo-1.0", + "dex-1", + "foundry-1", + "foundrygtk-1", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "giounix-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "gtksource-5", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "peas-2" + ] + }, + "foundrygtk-1": { + "published": "2026-09-10T22:50:16.128Z", + "dependencies": [ + "cairo-1.0", + "dex-1", + "foundry-1", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "giounix-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "gtksource-5", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "peas-2" + ] + }, + "fprint-2.0": { + "published": "2026-09-10T22:51:01.719Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gusb-1.0", + "json-1.0" + ] + }, + "freetype2-2.0": { + "published": "2026-09-10T22:52:43.725Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "fwupd-2.0": { + "published": "2026-09-10T22:52:03.548Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gamerzilla-0.1": { + "published": "2026-09-10T22:50:57.945Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "gandiva-1.0": { + "published": "2026-09-10T22:52:45.248Z", + "dependencies": [ + "arrow-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "garcon-1.0": { + "published": "2026-09-10T22:51:18.762Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxfce4util-1.0" + ] + }, + "garcongtk-1.0": { + "published": "2026-09-10T22:54:07.229Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "garcon-1.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "libxfce4ui-2.0", + "libxfce4util-1.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gc-1.0": { + "published": "2026-09-10T22:52:34.958Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "gcab-1.0": { + "published": "2026-09-10T22:52:45.590Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gcalc-1": { + "published": "2026-09-10T22:57:11.710Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gcalc-2": { + "published": "2026-09-10T22:52:11.787Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gci-1": { + "published": "2026-09-10T22:52:57.453Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gck-1": { + "published": "2026-09-10T22:52:33.704Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gck-2": { + "published": "2026-09-10T22:54:51.715Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gconf-2.0": { + "published": "2026-09-10T22:52:54.680Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "gcr-3": { + "published": "2026-09-10T22:53:08.249Z", + "dependencies": [ + "gck-1", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gcr-4": { + "published": "2026-09-10T22:54:14.259Z", + "dependencies": [ + "gck-2", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gcrgtk3-4": { + "published": "2026-09-10T22:54:45.464Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gck-2", + "gcr-4", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gcrgtk4-4": { + "published": "2026-09-10T22:53:40.104Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gck-2", + "gcr-4", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gcrui-3": { + "published": "2026-09-10T22:53:50.681Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gck-1", + "gcr-3", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gd-1.0": { + "published": "2026-09-10T22:54:01.143Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gda-5.0": { + "published": "2026-09-10T22:54:11.775Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0", + "libxml2-2.0" + ] + }, + "gda-6.0": { + "published": "2026-09-10T22:57:00.340Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxml2-2.0" + ] + }, + "gdata-0.0": { + "published": "2026-09-10T22:54:33.165Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "goa-1.0", + "gobject-2.0", + "json-1.0", + "libxml2-2.0", + "soup-2.4" + ] + }, + "gdaui-5.0": { + "published": "2026-09-10T22:54:43.881Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gda-5.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "libxml2-2.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gdaui-6.0": { + "published": "2026-09-10T22:54:54.701Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gda-6.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "libxml2-2.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gdesktopenums-3.0": { + "published": "2026-09-10T22:55:04.966Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "gdk-2.0": { + "published": "2026-09-10T22:55:15.875Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "gdk-3.0": { + "published": "2026-09-10T22:55:26.362Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "gdk-4.0": { + "published": "2026-09-10T22:55:37.032Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gdkmacos-4.0": { + "published": "2026-09-10T22:55:48.267Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gdkpixbuf-2.0": { + "published": "2026-09-10T22:58:37.155Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gdkpixdata-2.0": { + "published": "2026-09-10T22:57:24.153Z", + "dependencies": [ + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gdkwayland-4.0": { + "published": "2026-09-10T22:57:13.862Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gdkwin32-4.0": { + "published": "2026-09-10T22:59:06.772Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0", + "win32-1.0" + ] + }, + "gdkx11-2.0": { + "published": "2026-09-10T22:58:48.870Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gdkx11-3.0": { + "published": "2026-09-10T22:56:51.161Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gdkx11-4.0": { + "published": "2026-09-10T22:57:56.789Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "gdl-3": { + "published": "2026-09-10T22:57:11.598Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gdm-1.0": { + "published": "2026-09-10T22:57:21.976Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gedit-3.0": { + "published": "2026-09-10T22:57:32.229Z", + "dependencies": [ + "amtk-5", + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "gtksource-300", + "harfbuzz-0.0", + "pango-1.0", + "tepl-6", + "xlib-2.0" + ] + }, + "gee-0.8": { + "published": "2026-09-10T22:57:42.440Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gee-1.0": { + "published": "2026-09-10T23:00:00.159Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "gegl-0.3": { + "published": "2026-09-10T22:58:57.766Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "gegl-0.4": { + "published": "2026-09-10T22:59:29.400Z", + "dependencies": [ + "babl-0.1", + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "geglgtk3-0.1": { + "published": "2026-09-10T22:59:18.515Z", + "dependencies": [ + "atk-1.0", + "babl-0.1", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gegl-0.4", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "geoclue-2.0": { + "published": "2026-09-10T22:59:28.903Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "geocodeglib-1.0": { + "published": "2026-09-10T22:59:39.106Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "soup-2.4" + ] + }, + "geocodeglib-2.0": { + "published": "2026-09-10T23:00:30.783Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "soup-3.0" + ] + }, + "gepub-0.5": { + "published": "2026-09-10T22:59:04.597Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "javascriptcore-4.0", + "libxml2-2.0", + "pango-1.0", + "soup-2.4", + "webkit2-4.0", + "xlib-2.0" + ] + }, + "gepub-0.7": { + "published": "2026-09-10T23:00:11.283Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "javascriptcore-4.1", + "libxml2-2.0", + "pango-1.0", + "soup-3.0", + "webkit2-4.1", + "xlib-2.0" + ] + }, + "ges-1.0": { + "published": "2026-09-10T22:59:24.847Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstpbutils-1.0", + "gstvideo-1.0" + ] + }, + "gexiv2-0.10": { + "published": "2026-09-10T23:02:12.787Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gexiv2-0.16": { + "published": "2026-09-10T22:59:45.392Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gfbgraph-0.2": { + "published": "2026-09-10T22:59:55.505Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "rest-0.7", + "soup-2.4" + ] + }, + "gfbgraph-0.3": { + "published": "2026-09-10T23:06:17.407Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "rest-0.7", + "soup-2.4" + ] + }, + "gfls-1": { + "published": "2026-09-10T23:00:17.434Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "ggit-1.0": { + "published": "2026-09-10T23:01:23.348Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gimp-3.0": { + "published": "2026-09-10T23:02:14.673Z", + "dependencies": [ + "babl-0.1", + "cairo-1.0", + "freetype2-2.0", + "gdkpixbuf-2.0", + "gegl-0.4", + "gexiv2-0.10", + "gio-2.0", + "giounix-2.0", + "gjs", + "glib-2.0", + "glibunix-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "gimpui-3.0": { + "published": "2026-09-10T23:00:48.919Z", + "dependencies": [ + "atk-1.0", + "babl-0.1", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gegl-0.4", + "gexiv2-0.10", + "gimp-3.0", + "gio-2.0", + "giounix-2.0", + "gjs", + "glib-2.0", + "glibunix-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gio-2.0": { + "published": "2026-09-10T23:01:55.991Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "giounix-2.0": { + "published": "2026-09-10T23:01:10.637Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "giowin32-2.0": { + "published": "2026-09-10T23:01:21.286Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "girepository-2.0": { + "published": "2026-09-10T23:04:10.052Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "girepository-3.0": { + "published": "2026-09-10T23:01:41.906Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gitg-1.0": { + "published": "2026-09-10T23:01:52.703Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gee-0.8", + "ggit-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "gtksource-4", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gitgext-1.0": { + "published": "2026-09-10T23:03:20.230Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gee-0.8", + "ggit-1.0", + "gio-2.0", + "gitg-1.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "gtksource-4", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gjs": { + "published": "2026-09-10T23:03:08.475Z", + "dependencies": [ + "cairo-1.0", + "gio-2.0", + "glib-2.0", + "gobject-2.0" + ] + }, + "gjsdbus-1.0": { + "published": "2026-09-10T23:03:18.425Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gjsprivate-1.0": { + "published": "2026-09-10T23:02:34.135Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gkbd-3.0": { + "published": "2026-09-10T23:03:39.333Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xkl-1.0", + "xlib-2.0" + ] + }, + "gl-1.0": { + "published": "2026-09-10T23:02:54.679Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "gladeui-2.0": { + "published": "2026-09-10T23:04:41.373Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "glib-2.0": { + "published": "2026-09-10T23:04:10.724Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "glibunix-2.0": { + "published": "2026-09-10T23:05:01.704Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "glibwin32-2.0": { + "published": "2026-09-10T23:03:36.034Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "gly-1": { + "published": "2026-09-10T23:03:46.602Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gly-2": { + "published": "2026-09-10T23:04:51.526Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "glygtk4-1": { + "published": "2026-09-10T23:07:17.129Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gly-1", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "glygtk4-2": { + "published": "2026-09-10T23:04:17.230Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gly-2", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gm-0": { + "published": "2026-09-10T23:05:23.201Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gmenu-3.0": { + "published": "2026-09-10T23:09:49.670Z", + "dependencies": [ + "gio-2.0", + "giounix-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gmime-2.6": { + "published": "2026-09-10T23:04:49.427Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gmime-3.0": { + "published": "2026-09-10T23:04:59.672Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gmodule-2.0": { + "published": "2026-09-10T23:06:25.536Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "gnomeautoar-0.1": { + "published": "2026-09-10T23:05:20.282Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gnomeautoargtk-0.1": { + "published": "2026-09-10T23:07:37.215Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gnomeautoar-0.1", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gnomebg-4.0": { + "published": "2026-09-10T23:07:47.740Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gnomedesktop-4.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gnomebluetooth-1.0": { + "published": "2026-09-10T23:06:47.075Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gnomebluetooth-3.0": { + "published": "2026-09-10T23:08:08.580Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gnomecmd-1.0": { + "published": "2026-09-10T23:07:48.962Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gnomedesktop-3.0": { + "published": "2026-09-10T23:07:18.205Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gnomedesktop-4.0": { + "published": "2026-09-10T23:08:09.459Z", + "dependencies": [ + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gnomekeyring-1.0": { + "published": "2026-09-10T23:08:20.631Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "gnomemaps-1.0": { + "published": "2026-09-10T23:07:49.589Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "shumate-1.0" + ] + }, + "gnomeqr-4.0": { + "published": "2026-09-10T23:07:04.534Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gnomeqrgtk-4.0": { + "published": "2026-09-10T23:09:21.754Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gnomeqr-4.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gnomerr-4.0": { + "published": "2026-09-10T23:07:25.076Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gnomedesktop-4.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "goa-1.0": { + "published": "2026-09-10T23:07:36.166Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gobject-2.0": { + "published": "2026-09-10T23:09:03.478Z", + "dependencies": [ + "gjs", + "glib-2.0" + ] + }, + "gom-1.0": { + "published": "2026-09-10T23:07:57.670Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "goocanvas-2.0": { + "published": "2026-09-10T23:10:16.426Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "goocanvas-3.0": { + "published": "2026-09-10T23:10:25.164Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "govf-0.1": { + "published": "2026-09-10T23:09:23.080Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "govirt-1.0": { + "published": "2026-09-10T23:09:13.309Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "rest-1.0", + "soup-3.0" + ] + }, + "gpaste-2": { + "published": "2026-09-10T23:09:43.681Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gpastegtk-3": { + "published": "2026-09-10T23:08:58.623Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gpaste-2", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gpastegtk-4": { + "published": "2026-09-10T23:09:09.117Z", + "dependencies": [ + "adw-1", + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gpaste-2", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gpiodglib-1.0": { + "published": "2026-09-10T23:09:19.555Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gplugin-1.0": { + "published": "2026-09-10T23:10:24.774Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gplugingtk4-1.0": { + "published": "2026-09-10T23:09:40.036Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gplugin-1.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gpseq-1.0": { + "published": "2026-09-10T23:10:45.772Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "granite-1.0": { + "published": "2026-09-10T23:10:56.093Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "granite-7.0": { + "published": "2026-09-10T23:11:06.603Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "graphene-1.0": { + "published": "2026-09-10T23:10:20.892Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "grl-0.1": { + "published": "2026-09-10T23:10:31.136Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "grl-0.2": { + "published": "2026-09-10T23:11:58.089Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "grl-0.3": { + "published": "2026-09-10T23:10:51.693Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "grlnet-0.1": { + "published": "2026-09-10T23:11:56.870Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "grlnet-0.2": { + "published": "2026-09-10T23:11:12.221Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "soup-2.4" + ] + }, + "grlnet-0.3": { + "published": "2026-09-10T23:12:59.291Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "soup-3.0" + ] + }, + "grlpls-0.2": { + "published": "2026-09-10T23:14:10.298Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "grl-0.2" + ] + }, + "grlpls-0.3": { + "published": "2026-09-10T23:11:42.921Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "grl-0.3" + ] + }, + "grss-0.7": { + "published": "2026-09-10T23:11:53.439Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxml2-2.0", + "soup-2.4" + ] + }, + "gsf-1": { + "published": "2026-09-10T23:12:03.959Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxml2-2.0" + ] + }, + "gsignon-1.0": { + "published": "2026-09-10T23:12:14.455Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gsignond-1.0": { + "published": "2026-09-10T23:12:25.206Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gsk-4.0": { + "published": "2026-09-10T23:13:50.603Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gsound-1.0": { + "published": "2026-09-10T23:12:45.841Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gspell-1": { + "published": "2026-09-10T23:12:56.187Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gssdp-1.0": { + "published": "2026-09-10T23:13:06.608Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "soup-2.4" + ] + }, + "gssdp-1.2": { + "published": "2026-09-10T23:13:17.045Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "soup-2.4" + ] + }, + "gssdp-1.6": { + "published": "2026-09-10T23:15:35.080Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "soup-3.0" + ] + }, + "gst-0.10": { + "published": "2026-09-10T23:13:37.685Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxml2-2.0" + ] + }, + "gst-1.0": { + "published": "2026-09-10T23:13:47.969Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gstallocators-1.0": { + "published": "2026-09-10T23:15:13.828Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0" + ] + }, + "gstanalytics-1.0": { + "published": "2026-09-10T23:14:08.333Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstvideo-1.0" + ] + }, + "gstapp-1.0": { + "published": "2026-09-10T23:15:33.796Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0" + ] + }, + "gstaudio-1.0": { + "published": "2026-09-10T23:16:36.520Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0" + ] + }, + "gstbadallocators-1.0": { + "published": "2026-09-10T23:15:33.645Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0" + ] + }, + "gstbadaudio-1.0": { + "published": "2026-09-10T23:15:43.916Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0" + ] + }, + "gstbase-0.10": { + "published": "2026-09-10T23:15:54.812Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-0.10", + "libxml2-2.0" + ] + }, + "gstbase-1.0": { + "published": "2026-09-10T23:16:25.002Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0" + ] + }, + "gstcheck-1.0": { + "published": "2026-09-10T23:15:19.795Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0" + ] + }, + "gstclapper-1.0": { + "published": "2026-09-10T23:15:30.180Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstpbutils-1.0", + "gsttag-1.0", + "gstvideo-1.0" + ] + }, + "gstcodecparsers-1.0": { + "published": "2026-09-10T23:16:56.660Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0" + ] + }, + "gstcodecs-1.0": { + "published": "2026-09-10T23:15:50.915Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstcodecparsers-1.0", + "gstvideo-1.0" + ] + }, + "gstcontroller-1.0": { + "published": "2026-09-10T23:16:58.106Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0" + ] + }, + "gstcuda-1.0": { + "published": "2026-09-10T23:16:12.581Z", + "dependencies": [ + "cudagst-1.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstgl-1.0", + "gstvideo-1.0" + ] + }, + "gstdxva-1.0": { + "published": "2026-09-10T23:16:23.267Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstcodecparsers-1.0", + "gstcodecs-1.0", + "gstvideo-1.0" + ] + }, + "gstfft-1.0": { + "published": "2026-09-10T23:16:34.231Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0" + ] + }, + "gstgl-1.0": { + "published": "2026-09-10T23:18:20.870Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstvideo-1.0" + ] + }, + "gstglegl-1.0": { + "published": "2026-09-10T23:16:54.959Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstgl-1.0", + "gstvideo-1.0" + ] + }, + "gstglwayland-1.0": { + "published": "2026-09-10T23:18:01.998Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstgl-1.0", + "gstvideo-1.0" + ] + }, + "gstglx11-1.0": { + "published": "2026-09-10T23:17:16.374Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstgl-1.0", + "gstvideo-1.0" + ] + }, + "gsthip-1.0": { + "published": "2026-09-10T23:17:26.975Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstvideo-1.0" + ] + }, + "gsthipgl-1.0": { + "published": "2026-09-10T23:19:45.031Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstgl-1.0", + "gsthip-1.0", + "gstvideo-1.0" + ] + }, + "gstinsertbin-1.0": { + "published": "2026-09-10T23:20:26.336Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0" + ] + }, + "gstinterfaces-0.10": { + "published": "2026-09-10T23:17:57.569Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-0.10", + "libxml2-2.0" + ] + }, + "gstmpegts-1.0": { + "published": "2026-09-10T23:18:07.916Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0" + ] + }, + "gstmse-1.0": { + "published": "2026-09-10T23:18:18.624Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0" + ] + }, + "gstnet-1.0": { + "published": "2026-09-10T23:18:29.291Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0" + ] + }, + "gstpbutils-0.10": { + "published": "2026-09-10T23:21:17.677Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-0.10", + "libxml2-2.0" + ] + }, + "gstpbutils-1.0": { + "published": "2026-09-10T23:19:45.065Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstvideo-1.0" + ] + }, + "gstplay-1.0": { + "published": "2026-09-10T23:19:00.321Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstpbutils-1.0", + "gsttag-1.0", + "gstvideo-1.0" + ] + }, + "gstplayer-1.0": { + "published": "2026-09-10T23:19:10.708Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstpbutils-1.0", + "gsttag-1.0", + "gstvideo-1.0" + ] + }, + "gstriff-1.0": { + "published": "2026-09-10T23:19:20.771Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0" + ] + }, + "gstrtp-1.0": { + "published": "2026-09-10T23:20:27.280Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0" + ] + }, + "gstrtsp-1.0": { + "published": "2026-09-10T23:19:41.533Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstsdp-1.0" + ] + }, + "gstrtspserver-1.0": { + "published": "2026-09-10T23:22:00.174Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstnet-1.0", + "gstrtsp-1.0", + "gstsdp-1.0" + ] + }, + "gstsdp-1.0": { + "published": "2026-09-10T23:20:57.929Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0" + ] + }, + "gsttag-0.10": { + "published": "2026-09-10T23:20:12.435Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-0.10", + "libxml2-2.0" + ] + }, + "gsttag-1.0": { + "published": "2026-09-10T23:22:29.450Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0" + ] + }, + "gsttranscoder-1.0": { + "published": "2026-09-10T23:21:49.196Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstpbutils-1.0", + "gstvideo-1.0" + ] + }, + "gstva-1.0": { + "published": "2026-09-10T23:21:39.144Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstvideo-1.0" + ] + }, + "gstvalidate-1.0": { + "published": "2026-09-10T23:20:54.082Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstpbutils-1.0", + "gstvideo-1.0" + ] + }, + "gstvideo-0.10": { + "published": "2026-09-10T23:22:00.463Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-0.10", + "gstbase-0.10", + "libxml2-2.0" + ] + }, + "gstvideo-1.0": { + "published": "2026-09-10T23:22:10.453Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0" + ] + }, + "gstvulkan-1.0": { + "published": "2026-09-10T23:23:01.577Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstvideo-1.0", + "vulkan-1.0" + ] + }, + "gstvulkanwayland-1.0": { + "published": "2026-09-10T23:21:35.658Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstvideo-1.0", + "gstvulkan-1.0", + "vulkan-1.0" + ] + }, + "gstvulkanxcb-1.0": { + "published": "2026-09-10T23:23:02.072Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gstvideo-1.0", + "gstvulkan-1.0", + "vulkan-1.0" + ] + }, + "gstwebrtc-1.0": { + "published": "2026-09-10T23:21:56.827Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstsdp-1.0" + ] + }, + "gsystem-1.0": { + "published": "2026-09-10T23:22:07.461Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gtd-1.0": { + "published": "2026-09-10T23:24:24.522Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gtef-2": { + "published": "2026-09-10T23:23:23.423Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "gtksource-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gthree-1.0": { + "published": "2026-09-10T23:25:16.148Z", + "dependencies": [ + "cairo-1.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "gthreegtk3-1.0": { + "published": "2026-09-10T23:22:49.758Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gthree-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gtk-2.0": { + "published": "2026-09-10T23:23:00.772Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "gtk-3.0": { + "published": "2026-09-10T23:27:21.447Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gtk-4.0": { + "published": "2026-09-10T23:23:22.450Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gtk4layershell-1.0": { + "published": "2026-09-10T23:25:39.890Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gtk4sessionlock-1.0": { + "published": "2026-09-10T23:24:37.310Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gtkchamplain-0.12": { + "published": "2026-09-10T23:25:08.814Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "champlain-0.12", + "clutter-1.0", + "cogl-1.0", + "coglpango-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "gtkclutter-1.0": { + "published": "2026-09-10T23:26:40.891Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-1.0", + "cogl-1.0", + "coglpango-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0" + ] + }, + "gtkfrdp-0.2": { + "published": "2026-09-10T23:25:30.068Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gtklayershell-0.1": { + "published": "2026-09-10T23:24:24.616Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gtkosxapplication-1.0": { + "published": "2026-09-10T23:24:35.091Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gtksessionlock-0.1": { + "published": "2026-09-10T23:24:45.295Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gtksource-2.0": { + "published": "2026-09-10T23:24:56.125Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "gtksource-3.0": { + "published": "2026-09-10T23:28:15.472Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gtksource-300": { + "published": "2026-09-10T23:25:17.606Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gtksource-4": { + "published": "2026-09-10T23:26:45.092Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gtksource-5": { + "published": "2026-09-10T23:25:39.187Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "gtkspell-3.0": { + "published": "2026-09-10T23:26:24.459Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gtkvnc-2.0": { + "published": "2026-09-10T23:28:07.065Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "gvnc-1.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gtop-2.0": { + "published": "2026-09-10T23:26:11.010Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "gucharmap-2.90": { + "published": "2026-09-10T23:26:21.603Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gudev-1.0": { + "published": "2026-09-10T23:27:27.045Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "guestfs-1.0": { + "published": "2026-09-10T23:26:42.640Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gupnp-1.0": { + "published": "2026-09-10T23:26:53.464Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gssdp-1.0", + "libxml2-2.0", + "soup-2.4" + ] + }, + "gupnp-1.2": { + "published": "2026-09-10T23:29:10.595Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gssdp-1.2", + "libxml2-2.0", + "soup-2.4" + ] + }, + "gupnp-1.6": { + "published": "2026-09-10T23:27:14.410Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gssdp-1.6", + "libxml2-2.0", + "soup-3.0" + ] + }, + "gupnpav-1.0": { + "published": "2026-09-10T23:29:32.274Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0", + "libxml2-2.0" + ] + }, + "gupnpdlna-1.0": { + "published": "2026-09-10T23:27:35.669Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstpbutils-1.0", + "gstvideo-1.0", + "libxml2-2.0" + ] + }, + "gupnpdlna-2.0": { + "published": "2026-09-10T23:28:40.996Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "gupnpdlnagst-2.0": { + "published": "2026-09-10T23:28:51.813Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstpbutils-1.0", + "gstvideo-1.0", + "gupnpdlna-2.0" + ] + }, + "gupnpigd-1.0": { + "published": "2026-09-10T23:28:07.280Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "gupnpigd-1.6": { + "published": "2026-09-10T23:29:13.721Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "gusb-1.0": { + "published": "2026-09-10T23:28:28.227Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0" + ] + }, + "gvc-1.0": { + "published": "2026-09-10T23:30:15.116Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gvnc-1.0": { + "published": "2026-09-10T23:29:43.288Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gvncpulse-1.0": { + "published": "2026-09-10T23:28:58.801Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gvnc-1.0" + ] + }, + "gweather-3.0": { + "published": "2026-09-10T23:30:04.741Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "gweather-4.0": { + "published": "2026-09-10T23:29:19.591Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gxml-0.14": { + "published": "2026-09-10T23:29:29.939Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxml2-2.0" + ] + }, + "gxml-0.16": { + "published": "2026-09-10T23:29:40.740Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxml2-2.0" + ] + }, + "gxml-0.18": { + "published": "2026-09-10T23:30:46.908Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxml2-2.0" + ] + }, + "gxml-0.20": { + "published": "2026-09-10T23:30:01.719Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxml2-2.0" + ] + }, + "gxps-0.1": { + "published": "2026-09-10T23:31:08.716Z", + "dependencies": [ + "cairo-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "gxps-1.0": { + "published": "2026-09-10T23:30:22.512Z", + "dependencies": [ + "cairo-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "handy-0.0": { + "published": "2026-09-10T23:31:28.094Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "handy-1": { + "published": "2026-09-10T23:31:38.253Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "harfbuzz-0.0": { + "published": "2026-09-10T23:33:00.962Z", + "dependencies": [ + "freetype2-2.0", + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "hex-4": { + "published": "2026-09-10T23:32:40.741Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "hs-1": { + "published": "2026-09-10T23:36:23.959Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "ianjuta-3.0": { + "published": "2026-09-10T23:31:24.800Z", + "dependencies": [ + "anjuta-3.0", + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gdl-3", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "ibus-1.0": { + "published": "2026-09-10T23:33:42.860Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "ical-3.0": { + "published": "2026-09-10T23:32:43.156Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "icalglib-3.0": { + "published": "2026-09-10T23:31:57.319Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "ide-1.0": { + "published": "2026-09-10T23:32:08.150Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "dazzle-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "girepository-3.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "gtksource-3.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "peas-1.0", + "template-1.0", + "xlib-2.0" + ] + }, + "ide-45": { + "published": "2026-09-10T23:33:54.994Z", + "dependencies": [ + "adw-1", + "cairo-1.0", + "dex-1", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "giounix-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "gtksource-5", + "harfbuzz-0.0", + "javascriptcore-6.0", + "panel-1", + "pango-1.0", + "pangocairo-1.0", + "peas-2", + "soup-3.0", + "template-1.0", + "vte-3.91", + "webkit-6.0" + ] + }, + "ide-46": { + "published": "2026-09-10T23:34:37.228Z", + "dependencies": [ + "adw-1", + "cairo-1.0", + "dex-1", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "giounix-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "gtksource-5", + "harfbuzz-0.0", + "javascriptcore-6.0", + "panel-1", + "pango-1.0", + "pangocairo-1.0", + "peas-2", + "soup-3.0", + "template-1.0", + "vte-3.91", + "webkit-6.0" + ] + }, + "ide-47": { + "published": "2026-09-10T23:33:57.350Z", + "dependencies": [ + "adw-1", + "cairo-1.0", + "dex-1", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "giounix-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "gtksource-5", + "harfbuzz-0.0", + "javascriptcore-6.0", + "panel-1", + "pango-1.0", + "pangocairo-1.0", + "peas-2", + "soup-3.0", + "template-1.0", + "vte-3.91", + "webkit-6.0" + ] + }, + "ide-49": { + "published": "2026-09-10T23:33:46.273Z", + "dependencies": [ + "adw-1", + "cairo-1.0", + "dex-1", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "giounix-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "gtksource-5", + "harfbuzz-0.0", + "javascriptcore-6.0", + "panel-1", + "pango-1.0", + "pangocairo-1.0", + "peas-2", + "soup-3.0", + "template-1.0", + "vte-3.91", + "webkit-6.0" + ] + }, + "ide-50": { + "published": "2026-09-10T23:33:57.743Z", + "dependencies": [ + "adw-1", + "cairo-1.0", + "dex-1", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "giounix-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "gtksource-5", + "harfbuzz-0.0", + "javascriptcore-6.0", + "panel-1", + "pango-1.0", + "pangocairo-1.0", + "peas-2", + "soup-3.0", + "template-1.0", + "vte-3.91", + "webkit-6.0" + ] + }, + "imsettings-1.8": { + "published": "2026-09-10T23:33:11.905Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "inputpad-1.1": { + "published": "2026-09-10T23:35:30.420Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "ipuz-1.0": { + "published": "2026-09-10T23:35:09.203Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0" + ] + }, + "javascriptcore-4.0": { + "published": "2026-09-10T23:34:39.096Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "javascriptcore-4.1": { + "published": "2026-09-10T23:33:53.640Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "javascriptcore-5.0": { + "published": "2026-09-10T23:41:15.375Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "javascriptcore-6.0": { + "published": "2026-09-10T23:35:29.489Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "jcat-1.0": { + "published": "2026-09-10T23:35:20.187Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0" + ] + }, + "jscore-3.0": { + "published": "2026-09-10T23:36:45.161Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "json-1.0": { + "published": "2026-09-10T23:34:44.646Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "jsonrpc-1.0": { + "published": "2026-09-10T23:35:50.968Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "keybinder-0.0": { + "published": "2026-09-10T23:35:06.195Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "keybinder-3.0": { + "published": "2026-09-10T23:35:16.570Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "kkc-1.0": { + "published": "2026-09-10T23:36:21.444Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0" + ] + }, + "langtag-0.6": { + "published": "2026-09-10T23:35:37.085Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "lasem-0.4": { + "published": "2026-09-10T23:36:43.229Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "lasem-0.6": { + "published": "2026-09-10T23:37:35.708Z", + "dependencies": [ + "cairo-1.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "lfb-0.0": { + "published": "2026-09-10T23:36:08.612Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "libinsane-1.0": { + "published": "2026-09-10T23:36:19.350Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "libmsi-1.0": { + "published": "2026-09-10T23:36:29.627Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "libosinfo-1.0": { + "published": "2026-09-10T23:37:15.095Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxml2-2.0" + ] + }, + "libproxy-1.0": { + "published": "2026-09-10T23:36:50.200Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "libsitra-0.1": { + "published": "2026-09-10T23:37:57.000Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0" + ] + }, + "libvirtgconfig-1.0": { + "published": "2026-09-10T23:37:11.162Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0", + "libxml2-2.0" + ] + }, + "libvirtglib-1.0": { + "published": "2026-09-10T23:39:29.868Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "libvirtgobject-1.0": { + "published": "2026-09-10T23:38:48.289Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libvirtgconfig-1.0", + "libvirtglib-1.0", + "libxml2-2.0" + ] + }, + "libvirtsandbox-1.0": { + "published": "2026-09-10T23:39:51.108Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libvirtgconfig-1.0", + "libvirtglib-1.0", + "libvirtgobject-1.0", + "libxml2-2.0" + ] + }, + "libxfce4panel-2.0": { + "published": "2026-09-10T23:37:53.275Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "libxfce4util-1.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "libxfce4ui-2.0": { + "published": "2026-09-10T23:38:03.557Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "libxfce4util-1.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "libxfce4util-1.0": { + "published": "2026-09-10T23:40:21.491Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "libxfce4windowing-0.0": { + "published": "2026-09-10T23:39:19.743Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "libxfce4windowingui-0.0": { + "published": "2026-09-10T23:38:34.684Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "libxfce4windowing-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "libxml2-2.0": { + "published": "2026-09-10T23:38:45.142Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "liferea-3.0": { + "published": "2026-09-10T23:39:51.312Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "json-1.0", + "libxml2-2.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "lightdm-1": { + "published": "2026-09-10T23:40:01.409Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "malcontent-0": { + "published": "2026-09-10T23:39:16.127Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "malcontentui-1": { + "published": "2026-09-10T23:40:21.359Z", + "dependencies": [ + "accountsservice-1.0", + "adw-1", + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "malcontent-0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "manette-0.2": { + "published": "2026-09-10T23:40:31.965Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gudev-1.0" + ] + }, + "manette-1": { + "published": "2026-09-10T23:39:46.566Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "mash-0.2": { + "published": "2026-09-10T23:40:52.514Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-1.0", + "cogl-1.0", + "coglpango-1.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "matedesktop-2.0": { + "published": "2026-09-10T23:40:07.268Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "matekbd-1.0": { + "published": "2026-09-10T23:42:24.958Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xkl-1.0", + "xlib-2.0" + ] + }, + "matemenu-2.0": { + "published": "2026-09-10T23:40:27.899Z", + "dependencies": [ + "gio-2.0", + "giounix-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "matepanelapplet-4.0": { + "published": "2026-09-10T23:40:38.182Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "mbim-1.0": { + "published": "2026-09-10T23:42:05.202Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "mediaart-1.0": { + "published": "2026-09-10T23:42:17.428Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "mediaart-2.0": { + "published": "2026-09-10T23:41:10.945Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "meta-10": { + "published": "2026-09-10T23:44:30.336Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-10", + "cogl-10", + "coglpango-10", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-11": { + "published": "2026-09-10T23:42:49.038Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-11", + "cogl-11", + "coglpango-11", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-12": { + "published": "2026-09-10T23:41:42.839Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-12", + "cogl-12", + "coglpango-12", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-13": { + "published": "2026-09-10T23:41:53.134Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-13", + "cogl-13", + "coglpango-13", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "mtk-13", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-14": { + "published": "2026-09-10T23:43:00.643Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-14", + "cogl-14", + "coglpango-14", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-14", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-15": { + "published": "2026-09-10T23:42:13.689Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-15", + "cogl-15", + "coglpango-15", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-15", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-16": { + "published": "2026-09-10T23:45:03.321Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-16", + "cogl-16", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-16", + "pango-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-17": { + "published": "2026-09-10T23:43:29.451Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-17", + "cogl-17", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-17", + "pango-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-18": { + "published": "2026-09-10T23:44:00.793Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-18", + "cogl-18", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-18", + "pango-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-3": { + "published": "2026-09-10T23:45:02.813Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-3", + "cogl-3", + "coglpango-3", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-4": { + "published": "2026-09-10T23:46:14.446Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-4", + "cogl-4", + "coglpango-4", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-5": { + "published": "2026-09-10T23:44:10.935Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-5", + "cogl-5", + "coglpango-5", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-51": { + "published": "2026-09-10T23:44:41.717Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-51", + "cogl-51", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "mtk-51", + "pango-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-6": { + "published": "2026-09-10T23:44:31.909Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-6", + "cogl-6", + "coglpango-6", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-7": { + "published": "2026-09-10T23:45:02.396Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-7", + "cogl-7", + "coglpango-7", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-8": { + "published": "2026-09-10T23:43:57.201Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-8", + "cogl-8", + "coglpango-8", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "meta-9": { + "published": "2026-09-10T23:46:44.514Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-9", + "cogl-9", + "coglpango-9", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "metatest-12": { + "published": "2026-09-10T23:44:17.941Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-12", + "cogl-12", + "coglpango-12", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "meta-12", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "metatest-13": { + "published": "2026-09-10T23:44:28.245Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-13", + "cogl-13", + "coglpango-13", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "meta-13", + "mtk-13", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "metatest-14": { + "published": "2026-09-10T23:44:38.573Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-14", + "cogl-14", + "coglpango-14", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "meta-14", + "mtk-14", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "metatest-15": { + "published": "2026-09-10T23:46:25.094Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-15", + "cogl-15", + "coglpango-15", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "meta-15", + "mtk-15", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "metatest-16": { + "published": "2026-09-10T23:46:14.525Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-16", + "cogl-16", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "meta-16", + "mtk-16", + "pango-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "metatest-17": { + "published": "2026-09-10T23:46:04.964Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-17", + "cogl-17", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "meta-17", + "mtk-17", + "pango-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "metatest-18": { + "published": "2026-09-10T23:46:14.612Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-18", + "cogl-18", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "meta-18", + "mtk-18", + "pango-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "metatest-51": { + "published": "2026-09-10T23:46:24.879Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-51", + "cogl-51", + "freetype2-2.0", + "gdesktopenums-3.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "meta-51", + "mtk-51", + "pango-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "midori-0.6": { + "published": "2026-09-10T23:46:55.980Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "girepository-3.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "javascriptcore-4.0", + "pango-1.0", + "peas-1.0", + "soup-2.4", + "webkit2-4.0", + "xlib-2.0" + ] + }, + "ministream-1": { + "published": "2026-09-10T23:45:49.808Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "mirage-3.2": { + "published": "2026-09-10T23:46:00.454Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "mks-1": { + "published": "2026-09-10T23:47:06.957Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "modemmanager-1.0": { + "published": "2026-09-10T23:47:16.826Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "modulemd-2.0": { + "published": "2026-09-10T23:47:47.810Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "mpid-3.0": { + "published": "2026-09-10T23:47:37.635Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "msg-0": { + "published": "2026-09-10T23:46:52.305Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "goa-1.0", + "gobject-2.0", + "json-1.0", + "soup-3.0" + ] + }, + "msg-1": { + "published": "2026-09-10T23:47:58.125Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "goa-1.0", + "gobject-2.0", + "json-1.0", + "soup-3.0" + ] + }, + "mtk-13": { + "published": "2026-09-10T23:47:13.506Z", + "dependencies": [ + "cairo-1.0", + "gjs", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "mtk-14": { + "published": "2026-09-10T23:47:24.286Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "mtk-15": { + "published": "2026-09-10T23:47:34.613Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "mtk-16": { + "published": "2026-09-10T23:50:52.815Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "mtk-17": { + "published": "2026-09-10T23:47:54.573Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "mtk-18": { + "published": "2026-09-10T23:48:05.240Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "mtk-51": { + "published": "2026-09-10T23:49:30.841Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0", + "graphene-1.0" + ] + }, + "mx-1.0": { + "published": "2026-09-10T23:51:07.158Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-1.0", + "cogl-1.0", + "coglpango-1.0", + "fontconfig-2.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "pangofc-1.0", + "pangoft2-1.0" + ] + }, + "mx-2.0": { + "published": "2026-09-10T23:50:42.890Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-1.0", + "cogl-1.0", + "coglpango-1.0", + "fontconfig-2.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "pangofc-1.0", + "pangoft2-1.0" + ] + }, + "mxgtk-1.0": { + "published": "2026-09-10T23:49:40.536Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "mypaint-1.6": { + "published": "2026-09-10T23:48:55.902Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "mypaintgegl-1.6": { + "published": "2026-09-10T23:50:42.364Z", + "dependencies": [ + "babl-0.1", + "gegl-0.4", + "gjs", + "glib-2.0", + "gobject-2.0", + "mypaint-1.6" + ] + }, + "nautilus-3.0": { + "published": "2026-09-10T23:49:16.184Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "nautilus-4.0": { + "published": "2026-09-10T23:51:32.702Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "nautilus-4.1": { + "published": "2026-09-10T23:49:36.366Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "nemo-3.0": { + "published": "2026-09-10T23:49:46.689Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "nemopreview-1.0": { + "published": "2026-09-10T23:49:57.019Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-1.0", + "cogl-1.0", + "coglpango-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstpbutils-1.0", + "gsttag-1.0", + "gstvideo-1.0", + "gtk-3.0", + "gtksource-4", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "pangocairo-1.0", + "xlib-2.0", + "xreaderdocument-1.5" + ] + }, + "networkmanager-1.0": { + "published": "2026-09-10T23:50:07.240Z", + "dependencies": [ + "dbusglib-1.0", + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "nice-0.1": { + "published": "2026-09-10T23:50:17.469Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "nm-1.0": { + "published": "2026-09-10T23:50:28.042Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "nma-1.0": { + "published": "2026-09-10T23:52:45.019Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "nm-1.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "nma4-1.0": { + "published": "2026-09-10T23:51:43.155Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "nm-1.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "nmclient-1.0": { + "published": "2026-09-10T23:50:58.418Z", + "dependencies": [ + "dbusglib-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "networkmanager-1.0" + ] + }, + "nmgtk-1.0": { + "published": "2026-09-10T23:53:15.633Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "dbusglib-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "networkmanager-1.0", + "nmclient-1.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "notify-0.7": { + "published": "2026-09-10T23:51:19.397Z", + "dependencies": [ + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "osmgpsmap-1.0": { + "published": "2026-09-10T23:51:29.986Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "ostree-1.0": { + "published": "2026-09-10T23:51:40.670Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "p11kit-1.0": { + "published": "2026-09-10T23:51:51.180Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "packagekitglib-1.0": { + "published": "2026-09-10T23:52:01.520Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "packagekitplugin-1.0": { + "published": "2026-09-10T23:52:11.996Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "packagekitglib-1.0" + ] + }, + "panel-1": { + "published": "2026-09-10T23:52:22.667Z", + "dependencies": [ + "adw-1", + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "panelapplet-4.0": { + "published": "2026-09-10T23:52:32.942Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gconf-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "pango-1.0": { + "published": "2026-09-10T23:53:38.754Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0" + ] + }, + "pangocairo-1.0": { + "published": "2026-09-10T23:52:53.165Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "pangofc-1.0": { + "published": "2026-09-10T23:53:03.296Z", + "dependencies": [ + "cairo-1.0", + "fontconfig-2.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "pangoft2-1.0": { + "published": "2026-09-10T23:54:09.023Z", + "dependencies": [ + "cairo-1.0", + "fontconfig-2.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangofc-1.0" + ] + }, + "pangoot-1.0": { + "published": "2026-09-11T00:00:34.446Z", + "dependencies": [ + "cairo-1.0", + "fontconfig-2.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangofc-1.0" + ] + }, + "pangoxft-1.0": { + "published": "2026-09-10T23:54:29.309Z", + "dependencies": [ + "cairo-1.0", + "fontconfig-2.0", + "freetype2-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "harfbuzz-0.0", + "pango-1.0", + "pangofc-1.0", + "pangoft2-1.0", + "pangoot-1.0", + "xft-2.0", + "xlib-2.0" + ] + }, + "pantheonwayland-1": { + "published": "2026-09-10T23:53:44.047Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "papersdocument-4.0": { + "published": "2026-09-10T23:53:54.484Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "papersview-4.0": { + "published": "2026-09-10T23:55:00.187Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0", + "papersdocument-4.0" + ] + }, + "parquet-1.0": { + "published": "2026-09-11T00:01:26.092Z", + "dependencies": [ + "arrow-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "parquet-23.0": { + "published": "2026-09-10T23:55:19.638Z", + "dependencies": [ + "arrow-23.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "passim-1.0": { + "published": "2026-09-10T23:54:34.693Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "peas-1.0": { + "published": "2026-09-10T23:54:44.911Z", + "dependencies": [ + "gio-2.0", + "girepository-3.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "peas-2": { + "published": "2026-09-10T23:55:51.171Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "peasgtk-1.0": { + "published": "2026-09-10T23:55:05.267Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "girepository-3.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "peas-1.0", + "xlib-2.0" + ] + }, + "phosh-0": { + "published": "2026-09-10T23:55:15.936Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gck-1", + "gcr-3", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gnomebluetooth-3.0", + "gnomedesktop-3.0", + "gobject-2.0", + "gtk-3.0", + "handy-1", + "harfbuzz-0.0", + "nm-1.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "plasma-1.0": { + "published": "2026-09-10T23:55:26.044Z", + "dependencies": [ + "arrow-1.0", + "arrowcuda-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "playerctl-2.0": { + "published": "2026-09-10T23:56:32.064Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "pluma-1.0": { + "published": "2026-09-10T23:55:46.403Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "gtksource-4", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "pms-1.0": { + "published": "2026-09-10T23:55:57.015Z", + "dependencies": [ + "adw-1", + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "pnl-1.0": { + "published": "2026-09-10T23:57:02.911Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "polkit-1.0": { + "published": "2026-09-10T23:56:18.250Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "polkitagent-1.0": { + "published": "2026-09-10T23:56:28.683Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "polkit-1.0" + ] + }, + "poppler-0.18": { + "published": "2026-09-10T23:58:15.239Z", + "dependencies": [ + "cairo-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "pqmarble-2": { + "published": "2026-09-10T23:56:49.939Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "qmi-1.0": { + "published": "2026-09-10T23:58:16.452Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "qrtr-1.0" + ] + }, + "qrtr-1.0": { + "published": "2026-09-10T23:57:11.067Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "rb-3.0": { + "published": "2026-09-10T23:57:21.565Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstaudio-1.0", + "gstbase-1.0", + "gstpbutils-1.0", + "gstvideo-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "libxml2-2.0", + "mpid-3.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "rest-0.7": { + "published": "2026-09-10T23:57:31.770Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "soup-2.4" + ] + }, + "rest-1.0": { + "published": "2026-09-10T23:57:42.463Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "soup-3.0" + ] + }, + "restextras-0.7": { + "published": "2026-09-10T23:59:09.035Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "libxml2-2.0", + "rest-0.7", + "soup-2.4" + ] + }, + "restextras-1.0": { + "published": "2026-09-10T23:58:03.250Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "rest-1.0", + "soup-3.0" + ] + }, + "retro-0.14": { + "published": "2026-09-10T23:58:13.706Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "retro-1": { + "published": "2026-09-11T00:02:33.060Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "retro-2": { + "published": "2026-09-10T23:58:34.320Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "rpmostree-1.0": { + "published": "2026-09-11T00:00:51.677Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "ostree-1.0" + ] + }, + "rsvg-2.0": { + "published": "2026-09-10T23:58:54.733Z", + "dependencies": [ + "cairo-1.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "rygelcore-2.6": { + "published": "2026-09-10T23:59:05.363Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gssdp-1.2", + "gupnp-1.2", + "libxml2-2.0", + "soup-2.4" + ] + }, + "rygelcore-2.8": { + "published": "2026-09-11T00:00:31.981Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gssdp-1.6", + "gupnp-1.6", + "libxml2-2.0", + "soup-3.0" + ] + }, + "rygelrenderer-2.6": { + "published": "2026-09-11T00:01:02.996Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gssdp-1.2", + "gupnp-1.2", + "gupnpav-1.0", + "libxml2-2.0", + "rygelcore-2.6", + "soup-2.4" + ] + }, + "rygelrenderer-2.8": { + "published": "2026-09-11T00:00:31.647Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gssdp-1.6", + "gupnp-1.6", + "gupnpav-1.0", + "libxml2-2.0", + "rygelcore-2.8", + "soup-3.0" + ] + }, + "rygelrenderergst-2.6": { + "published": "2026-09-10T23:59:46.698Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gssdp-1.2", + "gst-1.0", + "gupnp-1.2", + "gupnpav-1.0", + "libxml2-2.0", + "rygelcore-2.6", + "rygelrenderer-2.6", + "soup-2.4" + ] + }, + "rygelrenderergst-2.8": { + "published": "2026-09-10T23:59:57.156Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gssdp-1.6", + "gst-1.0", + "gupnp-1.6", + "gupnpav-1.0", + "libxml2-2.0", + "rygelcore-2.8", + "rygelrenderer-2.8", + "soup-3.0" + ] + }, + "rygelserver-2.6": { + "published": "2026-09-11T00:00:11.457Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gssdp-1.2", + "gupnp-1.2", + "gupnpav-1.0", + "libxml2-2.0", + "rygelcore-2.6", + "soup-2.4" + ] + }, + "rygelserver-2.8": { + "published": "2026-09-11T00:00:24.405Z", + "dependencies": [ + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gssdp-1.6", + "gupnp-1.6", + "gupnpav-1.0", + "libxml2-2.0", + "rygelcore-2.8", + "soup-3.0" + ] + }, + "secret-1": { + "published": "2026-09-11T00:01:30.872Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "secretunstable-0": { + "published": "2026-09-11T00:00:46.151Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "secret-1" + ] + }, + "shell-0.1": { + "published": "2026-09-11T00:00:57.328Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-11", + "clutter-11", + "cogl-11", + "coglpango-11", + "freetype2-2.0", + "gck-1", + "gcr-3", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "gvc-1.0", + "harfbuzz-0.0", + "json-1.0", + "meta-11", + "nm-1.0", + "pango-1.0", + "pangocairo-1.0", + "polkit-1.0", + "polkitagent-1.0", + "st-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "shell-10": { + "published": "2026-09-11T00:01:08.313Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-10", + "clutter-10", + "cogl-10", + "coglpango-10", + "freetype2-2.0", + "gck-1", + "gcr-3", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "gvc-1.0", + "harfbuzz-0.0", + "json-1.0", + "meta-10", + "nm-1.0", + "pango-1.0", + "pangocairo-1.0", + "polkit-1.0", + "polkitagent-1.0", + "st-10", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "shell-11": { + "published": "2026-09-11T00:01:19.471Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-11", + "clutter-11", + "cogl-11", + "coglpango-11", + "freetype2-2.0", + "gck-2", + "gcr-4", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "gvc-1.0", + "harfbuzz-0.0", + "json-1.0", + "meta-11", + "nm-1.0", + "pango-1.0", + "pangocairo-1.0", + "polkit-1.0", + "polkitagent-1.0", + "st-11", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "shell-12": { + "published": "2026-09-11T00:03:36.761Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-12", + "clutter-12", + "cogl-12", + "coglpango-12", + "freetype2-2.0", + "gck-2", + "gcr-4", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gvc-1.0", + "harfbuzz-0.0", + "json-1.0", + "meta-12", + "nm-1.0", + "pango-1.0", + "pangocairo-1.0", + "polkit-1.0", + "polkitagent-1.0", + "st-12", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "shell-13": { + "published": "2026-09-11T00:01:40.722Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-13", + "clutter-13", + "cogl-13", + "coglpango-13", + "freetype2-2.0", + "gck-2", + "gcr-4", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gvc-1.0", + "harfbuzz-0.0", + "json-1.0", + "meta-13", + "mtk-13", + "nm-1.0", + "pango-1.0", + "pangocairo-1.0", + "polkit-1.0", + "polkitagent-1.0", + "st-13", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "shell-14": { + "published": "2026-09-11T00:01:51.432Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-14", + "clutter-14", + "cogl-14", + "coglpango-14", + "freetype2-2.0", + "gck-2", + "gcr-4", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gvc-1.0", + "harfbuzz-0.0", + "meta-14", + "mtk-14", + "nm-1.0", + "pango-1.0", + "pangocairo-1.0", + "polkit-1.0", + "polkitagent-1.0", + "st-14", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "shell-15": { + "published": "2026-09-11T00:02:57.389Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-15", + "cogl-15", + "coglpango-15", + "freetype2-2.0", + "gck-2", + "gcr-4", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gvc-1.0", + "harfbuzz-0.0", + "meta-15", + "mtk-15", + "nm-1.0", + "pango-1.0", + "pangocairo-1.0", + "polkit-1.0", + "polkitagent-1.0", + "st-15", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "shell-16": { + "published": "2026-09-11T00:03:07.292Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-16", + "cogl-16", + "freetype2-2.0", + "gck-2", + "gcr-4", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gvc-1.0", + "harfbuzz-0.0", + "meta-16", + "mtk-16", + "nm-1.0", + "pango-1.0", + "polkit-1.0", + "polkitagent-1.0", + "st-16", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "shell-17": { + "published": "2026-09-11T00:02:22.937Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-17", + "cogl-17", + "freetype2-2.0", + "gck-2", + "gcr-4", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "giounix-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gvc-1.0", + "harfbuzz-0.0", + "meta-17", + "mtk-17", + "nm-1.0", + "pango-1.0", + "polkit-1.0", + "polkitagent-1.0", + "st-17", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "shell-18": { + "published": "2026-09-11T00:05:41.456Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-18", + "cogl-18", + "freetype2-2.0", + "gck-2", + "gcr-4", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "giounix-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gvc-1.0", + "harfbuzz-0.0", + "meta-18", + "mtk-18", + "nm-1.0", + "pango-1.0", + "polkit-1.0", + "polkitagent-1.0", + "st-18", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "shell-51": { + "published": "2026-09-11T00:02:43.580Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-51", + "cogl-51", + "freetype2-2.0", + "gck-2", + "gcr-4", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "giounix-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gvc-1.0", + "harfbuzz-0.0", + "meta-51", + "mtk-51", + "nm-1.0", + "pango-1.0", + "polkit-1.0", + "polkitagent-1.0", + "st-51", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "shell-9": { + "published": "2026-09-11T00:02:54.154Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-9", + "clutter-9", + "cogl-9", + "coglpango-9", + "freetype2-2.0", + "gck-1", + "gcr-3", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "gvc-1.0", + "harfbuzz-0.0", + "json-1.0", + "meta-9", + "nm-1.0", + "pango-1.0", + "pangocairo-1.0", + "polkit-1.0", + "polkitagent-1.0", + "st-9", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "shew-0": { + "published": "2026-09-11T00:05:11.461Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "shumate-1.0": { + "published": "2026-09-11T00:04:09.989Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "signon-2.0": { + "published": "2026-09-11T00:03:25.394Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "skk-1.0": { + "published": "2026-09-11T00:04:51.333Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "snapd-1": { + "published": "2026-09-11T00:03:46.105Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "snapd-2": { + "published": "2026-09-11T00:04:51.430Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "socialwebclient-0.25": { + "published": "2026-09-11T00:05:22.427Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "soup-2.4": { + "published": "2026-09-11T00:04:17.027Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "soup-3.0": { + "published": "2026-09-11T00:05:22.830Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "soupgnome-2.4": { + "published": "2026-09-11T00:05:32.952Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "soup-2.4" + ] + }, + "spelling-1": { + "published": "2026-09-11T00:05:23.090Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "gtksource-5", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "spiceclientglib-2.0": { + "published": "2026-09-11T00:04:59.360Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0" + ] + }, + "spiceclientgtk-3.0": { + "published": "2026-09-11T00:06:25.441Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "gstbase-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "spiceclientglib-2.0", + "xlib-2.0" + ] + }, + "st-1.0": { + "published": "2026-09-11T00:06:36.641Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-11", + "clutter-11", + "cogl-11", + "coglpango-11", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "meta-11", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "st-10": { + "published": "2026-09-11T00:06:25.463Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-10", + "clutter-10", + "cogl-10", + "coglpango-10", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "meta-10", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "st-11": { + "published": "2026-09-11T00:05:40.711Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-11", + "clutter-11", + "cogl-11", + "coglpango-11", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "meta-11", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "st-12": { + "published": "2026-09-11T00:05:51.157Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-12", + "clutter-12", + "cogl-12", + "coglpango-12", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "meta-12", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "st-13": { + "published": "2026-09-11T00:07:17.998Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-13", + "clutter-13", + "cogl-13", + "coglpango-13", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "json-1.0", + "meta-13", + "mtk-13", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "st-14": { + "published": "2026-09-11T00:06:12.442Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-14", + "clutter-14", + "cogl-14", + "coglpango-14", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "meta-14", + "mtk-14", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "st-15": { + "published": "2026-09-11T00:09:00.983Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-15", + "cogl-15", + "coglpango-15", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "meta-15", + "mtk-15", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "st-16": { + "published": "2026-09-11T00:06:32.951Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-16", + "cogl-16", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "meta-16", + "mtk-16", + "pango-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "st-17": { + "published": "2026-09-11T00:08:51.089Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-17", + "cogl-17", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "meta-17", + "mtk-17", + "pango-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "st-18": { + "published": "2026-09-11T00:06:53.554Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-18", + "cogl-18", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "meta-18", + "mtk-18", + "pango-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "st-51": { + "published": "2026-09-11T00:07:04.098Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "clutter-51", + "cogl-51", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "harfbuzz-0.0", + "meta-51", + "mtk-51", + "pango-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "st-9": { + "published": "2026-09-11T00:08:09.674Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "cally-9", + "clutter-9", + "cogl-9", + "coglpango-9", + "freetype2-2.0", + "gdesktopenums-3.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "gl-1.0", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "meta-9", + "pango-1.0", + "pangocairo-1.0", + "xfixes-4.0", + "xlib-2.0" + ] + }, + "sugarext-1.0": { + "published": "2026-09-11T00:07:24.744Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "sugargestures-1.0", + "xlib-2.0" + ] + }, + "sugargestures-1.0": { + "published": "2026-09-11T00:08:30.257Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "sushi-1.0": { + "published": "2026-09-11T00:09:00.912Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gst-1.0", + "gstbase-1.0", + "gsttag-1.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0", + "papersdocument-4.0", + "papersview-4.0" + ] + }, + "telepathyfarstream-0.6": { + "published": "2026-09-11T00:07:55.475Z", + "dependencies": [ + "farstream-0.2", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gst-1.0", + "telepathyglib-0.12" + ] + }, + "telepathyglib-0.12": { + "published": "2026-09-11T00:09:01.572Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "telepathylogger-0.2": { + "published": "2026-09-11T00:09:12.305Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "telepathyglib-0.12" + ] + }, + "template-1.0": { + "published": "2026-09-11T00:08:26.740Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "tepl-4": { + "published": "2026-09-11T00:08:37.052Z", + "dependencies": [ + "amtk-5", + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "gtksource-4", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "tepl-5": { + "published": "2026-09-11T00:09:42.251Z", + "dependencies": [ + "amtk-5", + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "gtksource-4", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "tepl-6": { + "published": "2026-09-11T00:09:53.495Z", + "dependencies": [ + "amtk-5", + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "gtksource-300", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "thunarx-3.0": { + "published": "2026-09-11T00:09:08.137Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "timezonemap-1.0": { + "published": "2026-09-11T00:10:14.592Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "json-1.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "totem-1.0": { + "published": "2026-09-11T00:09:29.345Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "totemplparser-1.0", + "xlib-2.0" + ] + }, + "totemplparser-1.0": { + "published": "2026-09-11T00:10:34.254Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "tracker-1.0": { + "published": "2026-09-11T00:09:49.446Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "tracker-2.0": { + "published": "2026-09-11T00:10:55.350Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "tracker-3.0": { + "published": "2026-09-11T00:10:10.320Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "trackercontrol-1.0": { + "published": "2026-09-11T00:10:20.741Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "trackercontrol-2.0": { + "published": "2026-09-11T00:11:47.797Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "trackerminer-1.0": { + "published": "2026-09-11T00:10:41.758Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "tracker-1.0" + ] + }, + "trackerminer-2.0": { + "published": "2026-09-11T00:11:48.044Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "translit-1.0": { + "published": "2026-09-11T00:11:58.380Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "tsparql-3.0": { + "published": "2026-09-11T00:11:13.287Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "udisks-2.0": { + "published": "2026-09-11T00:12:19.833Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "uhm-0.0": { + "published": "2026-09-11T00:11:34.340Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "soup-2.4" + ] + }, + "uhm-1.0": { + "published": "2026-09-11T00:13:20.726Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "soup-3.0" + ] + }, + "umockdev-1.0": { + "published": "2026-09-11T00:12:50.368Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0" + ] + }, + "unique-3.0": { + "published": "2026-09-11T00:12:05.746Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "unity-6.0": { + "published": "2026-09-11T00:13:12.068Z", + "dependencies": [ + "dbusmenu-0.4", + "dee-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "unity-7.0": { + "published": "2026-09-11T00:13:22.097Z", + "dependencies": [ + "dbusmenu-0.4", + "dee-1.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "unityextras-7.0": { + "published": "2026-09-11T00:13:32.766Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "unity-7.0" + ] + }, + "upowerglib-1.0": { + "published": "2026-09-11T00:13:43.421Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "vda-1": { + "published": "2026-09-11T00:12:58.176Z", + "dependencies": [ + "gcalc-2", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gxml-0.20", + "json-1.0", + "libxml2-2.0" + ] + }, + "vgda-1": { + "published": "2026-09-11T00:14:03.725Z", + "dependencies": [ + "gcalc-2", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gxml-0.20", + "json-1.0", + "libxml2-2.0", + "vda-1" + ] + }, + "vgpg-1": { + "published": "2026-09-11T00:14:13.372Z", + "dependencies": [ + "gcalc-2", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gxml-0.20", + "json-1.0", + "libxml2-2.0", + "vda-1", + "vgda-1" + ] + }, + "vgsl-1": { + "published": "2026-09-11T00:13:28.772Z", + "dependencies": [ + "gcalc-2", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gxml-0.20", + "json-1.0", + "libxml2-2.0", + "vda-1", + "vgda-1" + ] + }, + "vips-8.0": { + "published": "2026-09-11T00:16:17.764Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "vpg-1": { + "published": "2026-09-11T00:14:45.422Z", + "dependencies": [ + "gcalc-2", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gxml-0.20", + "json-1.0", + "libxml2-2.0", + "vda-1" + ] + }, + "vsqlite-1": { + "published": "2026-09-11T00:15:36.828Z", + "dependencies": [ + "gcalc-2", + "gee-0.8", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gxml-0.20", + "json-1.0", + "libxml2-2.0", + "vda-1" + ] + }, + "vte-0.0": { + "published": "2026-09-11T00:16:18.671Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "vte-2.91": { + "published": "2026-09-11T00:15:16.250Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "vte-3.91": { + "published": "2026-09-11T00:15:26.681Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "vte-4-2.91": { + "published": "2026-09-11T00:14:42.224Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "vulkan-1.0": { + "published": "2026-09-11T00:14:52.673Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "webkit-6.0": { + "published": "2026-09-11T00:15:03.251Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "javascriptcore-6.0", + "pango-1.0", + "pangocairo-1.0", + "soup-3.0" + ] + }, + "webkit2-4.0": { + "published": "2026-09-11T00:15:14.112Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "javascriptcore-4.0", + "pango-1.0", + "soup-2.4", + "xlib-2.0" + ] + }, + "webkit2-4.1": { + "published": "2026-09-11T00:15:24.657Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "javascriptcore-4.1", + "pango-1.0", + "soup-3.0", + "xlib-2.0" + ] + }, + "webkit2-5.0": { + "published": "2026-09-11T00:15:35.180Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "javascriptcore-5.0", + "pango-1.0", + "pangocairo-1.0", + "soup-3.0" + ] + }, + "webkit2webextension-4.0": { + "published": "2026-09-11T00:16:40.800Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "javascriptcore-4.0", + "pango-1.0", + "soup-2.4", + "xlib-2.0" + ] + }, + "webkit2webextension-4.1": { + "published": "2026-09-11T00:16:30.701Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "javascriptcore-4.1", + "pango-1.0", + "soup-3.0", + "xlib-2.0" + ] + }, + "webkit2webextension-5.0": { + "published": "2026-09-11T00:16:06.656Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "javascriptcore-5.0", + "pango-1.0", + "pangocairo-1.0", + "soup-3.0" + ] + }, + "webkitwebextension-6.0": { + "published": "2026-09-11T00:16:17.139Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "javascriptcore-6.0", + "pango-1.0", + "pangocairo-1.0", + "soup-3.0" + ] + }, + "webkitwebprocessextension-6.0": { + "published": "2026-09-11T00:16:27.740Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "javascriptcore-6.0", + "pango-1.0", + "pangocairo-1.0", + "soup-3.0" + ] + }, + "win32-1.0": { + "published": "2026-09-11T00:20:47.419Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "wnck-1.0": { + "published": "2026-09-11T00:16:49.016Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-2.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-2.0", + "harfbuzz-0.0", + "pango-1.0" + ] + }, + "wnck-3.0": { + "published": "2026-09-11T00:17:00.369Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "workbench-0": { + "published": "2026-09-11T00:17:11.403Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "gtksource-5", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0" + ] + }, + "wp-0.4": { + "published": "2026-09-11T00:18:16.763Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "wp-0.5": { + "published": "2026-09-11T00:17:32.303Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "xapp-1.0": { + "published": "2026-09-11T00:17:42.898Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "xdp-1.0": { + "published": "2026-09-11T00:17:53.727Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "xdpgtk3-1.0": { + "published": "2026-09-11T00:19:19.902Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xdp-1.0", + "xlib-2.0" + ] + }, + "xdpgtk4-1.0": { + "published": "2026-09-11T00:18:15.012Z", + "dependencies": [ + "cairo-1.0", + "freetype2-2.0", + "gdk-4.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "graphene-1.0", + "gsk-4.0", + "gtk-4.0", + "harfbuzz-0.0", + "pango-1.0", + "pangocairo-1.0", + "xdp-1.0" + ] + }, + "xed-1.0": { + "published": "2026-09-11T00:19:41.460Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "gtksource-4", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "xfconf-0": { + "published": "2026-09-11T00:19:30.936Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "xfixes-4.0": { + "published": "2026-09-11T00:18:46.040Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "xft-2.0": { + "published": "2026-09-11T00:19:51.561Z", + "dependencies": [ + "gjs", + "gobject-2.0", + "xlib-2.0" + ] + }, + "xkl-1.0": { + "published": "2026-09-11T00:23:15.779Z", + "dependencies": [ + "gjs", + "glib-2.0", + "gobject-2.0", + "xlib-2.0" + ] + }, + "xlib-2.0": { + "published": "2026-09-11T00:20:52.587Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "xmlb-2.0": { + "published": "2026-09-11T00:20:22.446Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "xrandr-1.3": { + "published": "2026-09-11T00:19:37.208Z", + "dependencies": [ + "gjs", + "gobject-2.0" + ] + }, + "xreaderdocument-1.5": { + "published": "2026-09-11T00:19:47.764Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "xreaderview-1.5": { + "published": "2026-09-11T00:20:53.539Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0", + "xreaderdocument-1.5" + ] + }, + "zbar-1.0": { + "published": "2026-09-11T00:21:03.854Z", + "dependencies": [ + "atk-1.0", + "cairo-1.0", + "freetype2-2.0", + "gdk-3.0", + "gdkpixbuf-2.0", + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gtk-3.0", + "harfbuzz-0.0", + "pango-1.0", + "xlib-2.0" + ] + }, + "zeitgeist-2.0": { + "published": "2026-09-11T00:20:18.858Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0" + ] + }, + "zpj-0.0": { + "published": "2026-09-11T00:20:29.221Z", + "dependencies": [ + "gio-2.0", + "gjs", + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "json-1.0", + "rest-0.7", + "soup-2.4" + ] + } + } +} \ No newline at end of file diff --git a/.github/release-script/package-lock.json b/.github/release-script/package-lock.json index 2cb1a88f28..44a6363c0f 100644 --- a/.github/release-script/package-lock.json +++ b/.github/release-script/package-lock.json @@ -1,15 +1,19 @@ { "name": "release-script", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "release-script", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", + "dependencies": { + "semver": "^7.8.5" + }, "devDependencies": { "@types/node": "^24.3.0", + "@types/semver": "^7.8.0", "typescript": "^5.9.2" } }, @@ -23,6 +27,25 @@ "undici-types": "~7.10.0" } }, + "node_modules/@types/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-1mAINjtQCXXeLkJ9ehXkwOcBpqtLxiVtKhpUf83DdRNdQKV0iXZpaHYqRr7nj+wvxuJzoAmAwXI+sCNMv1CzLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/typescript": { "version": "5.9.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", diff --git a/.github/release-script/package.json b/.github/release-script/package.json index 1b3da544f3..3dc74e176f 100644 --- a/.github/release-script/package.json +++ b/.github/release-script/package.json @@ -5,6 +5,8 @@ "private": true, "scripts": { "check": "tsc --noEmit", + "test": "node --test --experimental-strip-types --no-warnings src/publish-plan.test.ts", + "test:e2e": "node test/e2e.mjs", "start": "node --experimental-specifier-resolution=node --experimental-strip-types --experimental-transform-types --no-warnings ./src/index.ts" }, "author": "", @@ -12,6 +14,10 @@ "description": "", "devDependencies": { "@types/node": "^24.3.0", + "@types/semver": "^7.8.0", "typescript": "^5.9.2" + }, + "dependencies": { + "semver": "^7.8.5" } } diff --git a/.github/release-script/src/index.ts b/.github/release-script/src/index.ts index 2ca102ea83..ed19246d9a 100644 --- a/.github/release-script/src/index.ts +++ b/.github/release-script/src/index.ts @@ -1,6 +1,18 @@ import { spawn } from "node:child_process"; -import { readdir, readFile, stat } from "node:fs/promises"; -import { basename, dirname, join } from "node:path"; +import { mkdtemp, readdir, readFile, rm, stat, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { basename, dirname, join, resolve } from "node:path"; +import { satisfies } from "semver"; + +import { + type ClosureGap, + closureGaps, + describeGap, + planPublishOrder, + type PublishGroup, + type RegistryView, + runtimeDependencies, +} from "./publish-plan.ts"; // Configuration and types interface Config { @@ -18,6 +30,15 @@ interface Config { * of the two happened to be on disk β€” and silently report success for the other. */ root: string; + /** + * Publish nothing; only ask whether what is ALREADY on the registry resolves. + * + * The same gate `publishPendingPackages` runs after every group, pointed at the current state + * instead of at a sweep in progress. It exists so the invariant can be asked at any time β€” + * after a release that was interrupted, or when a consumer reports a `notarget` and nobody + * knows yet which repository the cause lives in. + */ + verifyOnly: boolean; /** * How this run authenticates to npm. BOTH are supported on purpose. * @@ -37,6 +58,12 @@ interface Package { name: string; version: string; rootFolder: string; + /** + * Every RUNTIME dependency, name β†’ range. This is what decides the publish ORDER and what + * the closure gate checks β€” see `publish-plan.ts`. `devDependencies` are excluded: they are + * not installed for a consumer, so they can neither break an install nor constrain a sweep. + */ + dependencies: Record; } interface PackageStatus { @@ -363,6 +390,7 @@ function showUsage(): void { console.log(" --dry-run, -d Show what would be published without actually publishing"); console.log(" --continue-on-error, -c Continue processing even if some packages fail"); console.log(" --root Scan only for packages (default: the whole repository)"); + console.log(" --verify-only Publish nothing; check that what is already published resolves"); console.log(" --help, -h Show this help message"); console.log(""); console.log("Environment variables:"); @@ -373,6 +401,21 @@ function showUsage(): void { console.log(""); } +/** + * Is this the public npm registry? Decides `--provenance`, and nothing else. + * + * Matched on the HOST, not on a substring of the URL: `https://evil.example/registry.npmjs.org/` + * contains the name and is not npm. + */ +function isPublicNpmRegistry(url: string): boolean { + try { + const host = new URL(url).host.toLowerCase(); + return host === "registry.npmjs.org" || host === "registry.yarnpkg.com"; + } catch { + return false; + } +} + function normalizeRegistryUrl(url: string): string { let result = url; if (!result.startsWith("http")) { @@ -388,12 +431,13 @@ function getApiUrl(registry: string, packageName: string): string { return `${baseUrl}${encodeURIComponent(packageName)}`; } -function parseArgs(): Pick { +function parseArgs(): Pick { const args = process.argv; return { dryRun: args.includes("--dry-run") || args.includes("-d"), continueOnError: args.includes("--continue-on-error") || args.includes("-c"), root: parseRoot(args), + verifyOnly: args.includes("--verify-only"), }; } @@ -489,6 +533,7 @@ async function parsePackageJson(packageFile: string): Promise { name: data.name, version: data.version, rootFolder: dirname(packageFile), + dependencies: runtimeDependencies(data), }; } @@ -606,7 +651,13 @@ async function publishPackageOnce(pkg: Package, config: Config): Promise { const env = { ...process.env } as NodeJS.ProcessEnv; if (config.authMode === "token" && config.token) env.NODE_AUTH_TOKEN = config.token; else delete env.NODE_AUTH_TOKEN; - const args = ["publish", "--tag", "latest", "--access", "public", "--provenance", "--registry", config.registry]; + // `--provenance` is a public-npm feature: it needs a sigstore-backed registry and a CI + // provider npm recognises. Asking for it against any other registry makes the publish fail + // for a reason that has nothing to do with the package β€” which is also what made this + // script untestable end to end, since a local registry could never get past the first + // publish. The flag is therefore tied to the registry it belongs to, not to the run. + const args = ["publish", "--tag", "latest", "--access", "public", "--registry", config.registry]; + if (isPublicNpmRegistry(config.registry)) args.push("--provenance"); const proc = spawn("npm", args, { cwd: pkg.rootFolder, @@ -620,6 +671,10 @@ async function publishPackageOnce(pkg: Package, config: Config): Promise { proc.stderr.on("data", (data) => { stderr += data.toString(); }); + // stdout is piped and MUST be drained. An undrained pipe fills at 64 KB and the child + // blocks on its next write β€” forever, or until the timeout above turns a chatty publish + // into "timed out", which reads like a slow registry rather than a full buffer. + proc.stdout.on("data", () => {}); proc.on("error", (err) => { clearTimeout(timeoutId); @@ -677,15 +732,29 @@ async function publishPackageWithRetry(pkg: Package, config: Config): Promise { - // Get project root (3 levels up from .github/release-script/src/) - const scriptDir = new URL(".", import.meta.url).pathname; - const projectRoot = join(scriptDir, "..", "..", "..", root); + // Relative to the WORKING DIRECTORY, not to where this file happens to live. + // + // It used to be three levels up from `.github/release-script/src/`, which meant the scan + // target was this repository no matter where you stood β€” so `--root` could name a directory + // inside it and nothing else. Both workflows run from the repository root, so they are + // unaffected; what changes is that pointing the publisher at another tree is now possible at + // all, which is what lets it be tested end to end against a throwaway registry. `parseRoot` + // still refuses absolute paths and `..`, so `--root` cannot climb out of where it was run. + const projectRoot = resolve(process.cwd(), root); console.log(`πŸ“ Scanning ${projectRoot} for packages...`); const packageFiles = await findAllPackageFiles(projectRoot); console.log(`πŸ“¦ Found ${packageFiles.length} package.json files`); + // A sweep over nothing used to report "completed successfully". Whatever the cause β€” the wrong + // working directory, a `--root` that does not exist yet, a generation step that was skipped β€” + // a publisher that publishes nothing has not succeeded, and saying so here names the cause + // while the summary at the end would not. + if (packageFiles.length === 0) { + throw new Error(`no package.json found under ${projectRoot} β€” nothing to publish`); + } + const packages = await Promise.all(packageFiles.map((file) => parsePackageJson(file))); return packages; @@ -717,7 +786,7 @@ const WHOAMI_TIMEOUT_MS = 30_000; * `--dry-run` still works everywhere; only the writing path is gated. */ function assertRunningInCi(config: Config): void { - if (config.dryRun) return; + if (config.dryRun || config.verifyOnly) return; const inCi = process.env.GITHUB_ACTIONS === "true" || process.env.CI === "true"; if (inCi) return; if (process.env.ALLOW_PUBLISH_OUTSIDE_CI === "1") { @@ -731,7 +800,7 @@ function assertRunningInCi(config: Config): void { } async function assertCanAuthenticate(config: Config): Promise { - if (config.dryRun) return; + if (config.dryRun || config.verifyOnly) return; if (config.authMode === "oidc") { console.log("πŸ” Auth mode: OIDC (npm Trusted Publishing) β€” no token configured"); @@ -839,47 +908,182 @@ async function checkAllStatuses( return statuses; } -// Phase 2: Publish only packages that need it, in batches +/** + * The registry, asked live, with a POSITIVE-only cache. + * + * Only "yes, these versions are there" is cached. A negative is never cached, because a negative + * is the interesting answer and it is the one that changes: the whole point of the closure gate + * is to ask again a moment later and see whether the registry's replicas have caught up. + */ +class LiveRegistry implements RegistryView { + private readonly known = new Map(); + + constructor(private readonly registry: string) {} + + /** Seed from Phase 1, which already fetched every package in the run. */ + seed(statuses: Map): void { + for (const [name, status] of statuses) { + if (status.exists && status.versions.length > 0) this.known.set(name, status.versions); + } + } + + /** A package this run just published β€” drop any stale "what the registry had before" answer. */ + invalidate(name: string): void { + this.known.delete(name); + } + + async publishedVersions(name: string): Promise { + const cached = this.known.get(name); + if (cached) return cached; + + const response = await fetch(getApiUrl(this.registry, name), { + headers: { Accept: "application/json", "User-Agent": "ts-for-gir-release-script/1.0.0" }, + signal: AbortSignal.timeout(API_TIMEOUT_MS), + }); + if (response.status === 404) return null; + if (!response.ok) throw new HttpStatusError(response.status, `Registry responded with ${response.status}`); + + const data = (await response.json()) as { versions?: Record }; + const versions = Object.keys(data.versions ?? {}); + if (versions.length === 0) return null; + this.known.set(name, versions); + return versions; + } +} + +/** + * How long a gap may be blamed on registry lag before it is called an ordering defect. + * + * A package this process uploaded is not instantly visible to every read replica, so the first + * look after a publish can legitimately answer "not there". That window is seconds. Waiting + * longer than this would turn the gate's whole purpose β€” being red DURING the window β€” into a + * slow green, so the budget is bounded and small. + */ +const CLOSURE_LAG_BUDGET_MS = Math.max(0, getEnvInt("NPM_CLOSURE_LAG_MS", 60_000)); +const CLOSURE_LAG_STEP_MS = Math.max(250, getEnvInt("NPM_CLOSURE_LAG_STEP_MS", 5_000)); + +/** + * THE invariant, checked after every publish group: a consumer installing what we just published + * can resolve it. Asked of the registry, not of our own bookkeeping β€” "we published it" is the + * answer we already have. + * + * Edges inside the group are exempt. They must be: the `@girs` graph has a six-member cycle + * (cairo-1.0 Β· gio-2.0 Β· gjs Β· glib-2.0 Β· gmodule-2.0 Β· gobject-2.0), and no order makes a cycle + * member's closure complete at its own publish instant. See `publish-plan.ts`. + */ +async function verifyGroupClosure( + group: PublishGroup, + registry: LiveRegistry, + plannedGroupOf: Map, +): Promise { + const deadline = Date.now() + CLOSURE_LAG_BUDGET_MS; + let gaps = await closureGaps(group.members, registry, satisfies); + + while (gaps.length > 0 && Date.now() < deadline) { + console.log( + `⏳ group ${group.index}: ${gaps.length} dependency/ies not resolvable yet, re-asking the registry…`, + ); + await sleep(CLOSURE_LAG_STEP_MS); + for (const gap of gaps) registry.invalidate(gap.dependency); + gaps = await closureGaps(group.members, registry, satisfies); + } + + for (const gap of gaps) { + // A GitHub annotation, so the failure is visible at the moment it happens rather than only + // in the 700-package log tail. The message names the package AND the repository, which is + // what `npm error notarget No matching version found for @girs/pango-1.0@^4.9.0` does not. + console.log(`::error title=Incomplete closure::${describeGap(gap)}`); + const plannedAt = plannedGroupOf.get(gap.dependency); + if (plannedAt !== undefined && plannedAt > group.index) { + throw new Error( + `publish plan is wrong: ${gap.package} (group ${group.index}) needs ${gap.dependency}, ` + + `which this run does not publish until group ${plannedAt}. Stopping rather than widening the window.`, + ); + } + } + + return gaps; +} + +/** + * The next run of groups that can go out together: consecutive in the plan AND independent of + * one another. + * + * `NPM_BATCH_SIZE` is a PACING knob (batch=1 in release.yml, because concurrent provenance + * signing draws E429), not a licence to publish a dependent beside its dependency. Checking + * independence is what lets the knob keep its old meaning without reintroducing the defect. + */ +function takeIndependentRun(plan: PublishGroup[], from: number, max: number): PublishGroup[] { + const run: PublishGroup[] = [plan[from]]; + const inRun = new Set(plan[from].members.map((member) => member.name)); + for (let i = from + 1; i < plan.length && run.length < max; i++) { + const candidate = plan[i]; + const dependsOnRun = candidate.members.some((member) => + Object.keys(member.dependencies).some((dep) => inRun.has(dep)), + ); + if (dependsOnRun) break; + run.push(candidate); + for (const member of candidate.members) inRun.add(member.name); + } + return run; +} + +// Phase 2: Publish what needs publishing, in topological order, checking the closure as we go async function publishPendingPackages( packages: Package[], statuses: Map, config: Config, -): Promise<{ alreadyPublished: number; processed: number; errors: number }> { - // Split into already-published and needs-publish - const needsPublish: { pkg: Package; isUpdate: boolean }[] = []; - let alreadyPublished = 0; + registry: LiveRegistry, +): Promise<{ alreadyPublished: number; processed: number; errors: number; published: Package[] }> { + // The plan is built over the WHOLE set, not over the subset that needs publishing. A package + // that is already on the registry is still a dependency, and leaving it out of the graph would + // make the remaining order look like it had no constraints. + const plan = planPublishOrder(packages); + const plannedGroupOf = new Map(); + for (const group of plan) for (const member of group.members) plannedGroupOf.set(member.name, group.index); + const cycles = plan.filter((group) => group.members.length > 1); + console.log( + `🧭 Publish plan: ${plan.length} group(s) over ${packages.length} package(s)` + + (cycles.length > 0 + ? `, ${cycles.length} of them a dependency cycle: ` + + cycles.map((group) => `{${group.members.map((m) => m.name).join(" ")}}`).join(", ") + : ", no cycles"), + ); - for (const pkg of packages) { + const isPublished = (pkg: Package) => { const status = statuses.get(pkg.name); - if (status?.exists && status.versions.includes(pkg.version)) { - alreadyPublished++; - continue; - } - needsPublish.push({ pkg, isUpdate: status?.exists ?? false }); - } + return status?.exists === true && status.versions.includes(pkg.version); + }; - console.log(`πŸ“Š ${alreadyPublished} already published, ${needsPublish.length} to publish\n`); + const alreadyPublished = packages.filter(isPublished).length; + const pendingGroups = plan + .map((group) => ({ ...group, members: group.members.filter((member) => !isPublished(member)) })) + .filter((group) => group.members.length > 0); + const pendingCount = pendingGroups.reduce((n, group) => n + group.members.length, 0); - if (needsPublish.length === 0) { - return { alreadyPublished, processed: 0, errors: 0 }; + console.log(`πŸ“Š ${alreadyPublished} already published, ${pendingCount} to publish\n`); + + if (pendingCount === 0) { + return { alreadyPublished, processed: 0, errors: 0, published: [] }; } - console.log(`πŸš€ Phase 2: Publishing ${needsPublish.length} packages (batch size: ${BATCH_SIZE})...\n`); + console.log(`πŸš€ Phase 2: Publishing ${pendingCount} packages in plan order (batch size: ${BATCH_SIZE})...\n`); let processed = 0; let errors = 0; + const published: Package[] = []; - for (let i = 0; i < needsPublish.length; i += BATCH_SIZE) { - const batch = needsPublish.slice(i, i + BATCH_SIZE); - const batchNum = Math.floor(i / BATCH_SIZE) + 1; - const totalBatches = Math.ceil(needsPublish.length / BATCH_SIZE); + for (let i = 0; i < pendingGroups.length; ) { + const run = takeIndependentRun(pendingGroups, i, BATCH_SIZE); + const batch = run.flatMap((group) => group.members); + i += run.length; - console.log(`πŸ“¦ Batch ${batchNum}/${totalBatches} (${batch.map((b) => b.pkg.name).join(", ")})`); + console.log(`πŸ“¦ Groups ${run[0].index}…${run[run.length - 1].index} (${batch.map((p) => p.name).join(", ")})`); const batchResults = await Promise.allSettled( - batch.map(async ({ pkg, isUpdate }): Promise => { + batch.map(async (pkg): Promise => { try { - const action = isUpdate ? "update" : "create"; + const action = statuses.get(pkg.name)?.exists ? "update" : "create"; if (config.dryRun) { console.log(`πŸ“¦ [DRY RUN] Would ${action} ${pkg.name}@${pkg.version}`); @@ -887,7 +1091,7 @@ async function publishPendingPackages( } await publishPackageWithRetry(pkg, config); - return { result: isUpdate ? "updated" : "created", pkg }; + return { result: action === "update" ? "updated" : "created", pkg }; } catch (error) { const message = error instanceof Error ? error.message : "Unknown error"; console.error(`❌ ${pkg.name}: ${message}`); @@ -906,6 +1110,8 @@ async function publishPendingPackages( errors++; } else { processed++; + published.push(result.value.pkg); + registry.invalidate(result.value.pkg.name); } } else if (config.continueOnError) { console.error(`❌ Batch error: ${result.reason}`); @@ -915,18 +1121,140 @@ async function publishPendingPackages( } } - const progress = (((i + BATCH_SIZE) / needsPublish.length) * 100).toFixed(1); - console.log( - `βœ… Batch ${batchNum}/${totalBatches} done (${progress}%) - Processed: ${processed}, Errors: ${errors}\n`, - ); + // The gate. A dry run publishes nothing, so there is nothing yet for a consumer to resolve + // and the check would be red on every unreleased version β€” it is skipped, and said so. + if (!config.dryRun) { + for (const group of run) { + const gaps = await verifyGroupClosure(group, registry, plannedGroupOf); + if (gaps.length > 0) { + errors += gaps.length; + if (!config.continueOnError) { + throw new Error(`group ${group.index} published with an incomplete closure: ${describeGap(gaps[0])}`); + } + } + } + } + + const progress = ((processed + errors) / pendingCount * 100).toFixed(1); + console.log(`βœ… ${progress}% - Processed: ${processed}, Errors: ${errors}\n`); - // Delay between batches (not after the last one) - if (i + BATCH_SIZE < needsPublish.length && BATCH_DELAY_MS > 0) { + if (i < pendingGroups.length && BATCH_DELAY_MS > 0) { await sleep(BATCH_DELAY_MS); } } - return { alreadyPublished, processed, errors }; + return { alreadyPublished, processed, errors, published }; +} + +/** + * The last word, and the only one that is not our own: a REAL `npm install` of the whole + * published set into an empty directory. + * + * Everything above asks the registry what it holds. This asks npm to actually resolve and + * download it, which is a strictly stronger question and catches two things the packument + * cannot. A range nobody can satisfy β€” the `notarget` a consumer sees β€” and a version that + * exists in the metadata while its TARBALL does not: measured on `@girs/sdk-gnome-master@4.7.0`, + * where publish reported success, `npm view` listed the version with an attestation, and + * `npm install` answered E404. + * + * Measured cost for the full 716-package set on a cold cache: 5.5 minutes, 225 MB unpacked. + * Against a two-hour sweep that is the cheapest proof available that the release is installable. + */ +async function verifyInstallableClosure(packages: Package[], config: Config): Promise { + if (config.dryRun || packages.length === 0) return; + + const dir = await mkdtemp(join(tmpdir(), "girs-closure-")); + console.log(`\nπŸ”Ž Phase 3: resolving the published set from an empty directory (${packages.length} roots)…`); + + try { + await writeFile( + join(dir, "package.json"), + JSON.stringify( + { + name: "closure-probe", + version: "1.0.0", + private: true, + dependencies: Object.fromEntries(packages.map((pkg) => [pkg.name, pkg.version])), + }, + null, + 2, + ), + ); + + const { code, output } = await runNpm( + ["install", "--no-package-lock", "--no-audit", "--no-fund", "--ignore-scripts", "--registry", config.registry], + dir, + config.timeoutSec, + ); + + if (code !== 0) { + // npm's own words, because they are the words the consumer would have seen. + console.log(`::error title=Published set is not installable::${output.trim().split("\n").slice(-3).join(" ")}`); + throw new Error(`the published set does not install:\n${output.trim()}`); + } + console.log(`βœ… the published set installs from an empty directory`); + } finally { + await rm(dir, { recursive: true, force: true }); + } +} + +/** Run npm somewhere and collect what it said. Used by the closure probe, not by publishing. */ +function runNpm(args: string[], cwd: string, timeoutSec: number): Promise<{ code: number; output: string }> { + return new Promise((resolve, reject) => { + const proc = spawn("npm", args, { cwd, env: process.env, shell: true, stdio: "pipe" }); + let output = ""; + const timeoutId = setTimeout(() => { + proc.kill("SIGKILL"); + reject(new Error(`npm ${args[0]} timed out after ${timeoutSec}s`)); + }, timeoutSec * 1000); + proc.stdout.on("data", (chunk) => { + output += chunk.toString(); + }); + proc.stderr.on("data", (chunk) => { + output += chunk.toString(); + }); + proc.on("error", (err) => { + clearTimeout(timeoutId); + reject(err); + }); + proc.on("exit", (code) => { + clearTimeout(timeoutId); + resolve({ code: code ?? 1, output }); + }); + }); +} + +/** + * `--verify-only`: the gate, asked of the CURRENT registry instead of of a sweep in progress. + * + * Only packages that are actually published at their declared version are checked β€” an + * unpublished one has no closure to be incomplete. Same grouping, so the same cycle exemption + * applies; a member of a strongly connected component is checked only once every member of it + * is up, because until then no order could have made it resolvable. + */ +async function verifyPublishedClosure( + packages: Package[], + statuses: Map, + registry: LiveRegistry, +): Promise { + const isPublished = (pkg: Package) => { + const status = statuses.get(pkg.name); + return status?.exists === true && status.versions.includes(pkg.version); + }; + + const plan = planPublishOrder(packages); + const gaps: ClosureGap[] = []; + let checked = 0; + + for (const group of plan) { + if (!group.members.every(isPublished)) continue; + checked += group.members.length; + gaps.push(...(await closureGaps(group.members, registry, satisfies))); + } + + console.log(`\nπŸ”Ž Verified the closure of ${checked} published package(s) in ${plan.length} group(s)`); + for (const gap of gaps) console.log(`::error title=Incomplete closure::${describeGap(gap)}`); + return gaps; } async function main(): Promise { @@ -957,8 +1285,35 @@ async function main(): Promise { // Phase 1: Check all statuses in parallel const statuses = await checkAllStatuses(packages, config.registry); - // Phase 2: Publish only what's needed - const { alreadyPublished, processed, errors } = await publishPendingPackages(packages, statuses, config); + const registry = new LiveRegistry(config.registry); + registry.seed(statuses); + + if (config.verifyOnly) { + const gaps = await verifyPublishedClosure(packages, statuses, registry); + if (gaps.length > 0) { + throw new Error( + `${gaps.length} unresolvable dependency/ies in the published set:\n ` + + gaps.map(describeGap).join("\n "), + ); + } + console.log("βœ… every published package resolves against the registry"); + return; + } + + // Phase 2: Publish only what's needed, in topological order, gated after every group + const { alreadyPublished, processed, errors } = await publishPendingPackages( + packages, + statuses, + config, + registry, + ); + + // Phase 3: prove the whole set installs. Only after a sweep that published something and + // reported no errors β€” a failed sweep is already red, and a five-minute install that is + // certain to fail adds nothing but noise to the log that has to be read. + if (processed > 0 && errors === 0) { + await verifyInstallableClosure(packages, config); + } // Final summary console.log("πŸ“Š Final Summary:"); diff --git a/.github/release-script/src/publish-plan.test.ts b/.github/release-script/src/publish-plan.test.ts new file mode 100644 index 0000000000..ae25f0af03 --- /dev/null +++ b/.github/release-script/src/publish-plan.test.ts @@ -0,0 +1,276 @@ +/** + * The two halves of the publish mechanism, held to cases that must go BOTH ways. + * + * The point of this file is the negative arm. A closure gate that has never been red is not a + * gate β€” and this one has a historical set to be red on: `fixtures/girs-4.9.0.json` records the + * dependency edges of all 716 `@girs/*` packages of v4.9.0 together with the instant each of + * them actually reached the registry. Replaying that recorded sequence through the REAL gate + * (not a reimplementation of it) is the discriminator: + * + * - in the order v4.9.0 actually went out: 508 packages published with an incomplete closure + * - in the order `planPublishOrder` produces: 0 + * + * A gate that reports 0 on both is measuring the END state, which was correct at 00:23Z and has + * been correct at the end of every release ever run here. A gate that reports non-zero on both + * does not distinguish sorted from unsorted, and gets switched off after the second false red. + * + * The fixture is frozen on purpose. It is a recorded incident, like `CLASSIFIER_VECTORS` in + * index.ts β€” regenerating it from the working tree at test time would make the expected numbers + * drift with the next release and quietly stop testing the incident. + */ + +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { test } from "node:test"; +import { fileURLToPath } from "node:url"; +import { satisfies } from "semver"; + +import { + closureGaps, + describeGap, + type PlannablePackage, + planPublishOrder, + type PublishGroup, + type RegistryView, + runtimeDependencies, + stronglyConnectedComponents, +} from "./publish-plan.ts"; + +// --- the recorded release --------------------------------------------------------------- + +interface Fixture { + release: string; + packages: Record; +} + +const FIXTURE = JSON.parse( + readFileSync(fileURLToPath(new URL("../fixtures/girs-4.9.0.json", import.meta.url)), "utf-8"), +) as Fixture; + +const scoped = (name: string) => `@girs/${name}`; + +const RECORDED_PACKAGES: PlannablePackage[] = Object.entries(FIXTURE.packages).map(([name, entry]) => ({ + name: scoped(name), + version: FIXTURE.release, + // Every edge in the v4.9.0 tree is a caret on the release version β€” measured: 7637 of 7637. + dependencies: Object.fromEntries(entry.dependencies.map((dep) => [scoped(dep), `^${FIXTURE.release}`])), +})); + +const PUBLISHED_AT = new Map( + Object.entries(FIXTURE.packages).map(([name, entry]) => [scoped(name), Date.parse(entry.published)]), +); + +/** The registry as it looked once `published` had been uploaded and nothing else. */ +function registryHolding(published: Set, version = FIXTURE.release): RegistryView { + return { + async publishedVersions(name: string) { + return published.has(name) ? [version] : null; + }, + }; +} + +/** Run the real gate over a sequence of groups, publishing each one before checking it. */ +async function replay(order: PublishGroup[]) { + const published = new Set(); + const gaps = []; + for (const group of order) { + for (const member of group.members) published.add(member.name); + gaps.push(...(await closureGaps(group.members, registryHolding(published), satisfies))); + } + return { gaps, offenders: new Set(gaps.map((gap) => gap.package)) }; +} + +/** The same groups, sequenced by the instant each one finished under the recorded release. */ +function inRecordedOrder(plan: PublishGroup[]): PublishGroup[] { + const finishedAt = (group: PublishGroup) => + Math.max(...group.members.map((member) => PUBLISHED_AT.get(member.name) as number)); + return [...plan].sort((a, b) => finishedAt(a) - finishedAt(b)); +} + +// --- the graph -------------------------------------------------------------------------- + +test("the recorded release is the whole set and every edge lands inside it", () => { + assert.equal(RECORDED_PACKAGES.length, 716); + const names = new Set(RECORDED_PACKAGES.map((pkg) => pkg.name)); + for (const pkg of RECORDED_PACKAGES) { + for (const dep of Object.keys(pkg.dependencies)) { + assert.ok(names.has(dep), `${pkg.name} depends on ${dep}, which the release does not contain`); + } + } +}); + +test("the @girs graph is cyclic, and the cycle is six namespaces wide", () => { + // Not a hard-coded pair. GIR namespaces reference each other, and the next set can bring a + // different cycle; what is asserted is that the components are FOUND, and that this one is + // found whole β€” a gate that knew only about glib/gobject would exempt four members too few. + const plan = planPublishOrder(RECORDED_PACKAGES); + const cyclic = plan.filter((group) => group.members.length > 1); + assert.equal(cyclic.length, 1); + assert.deepEqual( + cyclic[0].members.map((member) => member.name).sort(), + ["@girs/cairo-1.0", "@girs/gio-2.0", "@girs/gjs", "@girs/glib-2.0", "@girs/gmodule-2.0", "@girs/gobject-2.0"], + ); + // It has nothing outside itself to wait for, so it goes first. + assert.equal(cyclic[0].index, 0); +}); + +test("the plan covers every package exactly once", () => { + const plan = planPublishOrder(RECORDED_PACKAGES); + const seen = plan.flatMap((group) => group.members.map((member) => member.name)); + assert.equal(seen.length, RECORDED_PACKAGES.length); + assert.equal(new Set(seen).size, RECORDED_PACKAGES.length); + assert.equal(plan.length, 711); +}); + +test("the plan is deterministic β€” a resumed release republishes in the order it started in", () => { + const a = planPublishOrder(RECORDED_PACKAGES).map((g) => g.members.map((m) => m.name).join("+")); + const b = planPublishOrder([...RECORDED_PACKAGES].reverse()).map((g) => g.members.map((m) => m.name).join("+")); + assert.deepEqual(a, b); +}); + +test("no group is planned before something it depends on", () => { + const plan = planPublishOrder(RECORDED_PACKAGES); + const groupOf = new Map(); + for (const group of plan) for (const member of group.members) groupOf.set(member.name, group.index); + for (const group of plan) { + for (const member of group.members) { + for (const dep of Object.keys(member.dependencies)) { + const at = groupOf.get(dep); + if (at === undefined) continue; + assert.ok(at <= group.index, `${member.name} (group ${group.index}) needs ${dep} (group ${at})`); + } + } + } +}); + +// --- the gate, both arms ---------------------------------------------------------------- + +test("NEGATIVE CONTROL: replaying the real v4.9.0 order turns the gate red 508 times", async () => { + const { gaps, offenders } = await replay(inRecordedOrder(planPublishOrder(RECORDED_PACKAGES))); + assert.equal(offenders.size, 508); + assert.equal(gaps.length, 3363); + // The one the consumer hit: adw-1 went out first and named pango-1.0, 96 minutes early. + assert.ok( + gaps.some((gap) => gap.package === "@girs/adw-1" && gap.dependency === "@girs/pango-1.0"), + "the gap gjsify's e2e legs died on is not among the findings", + ); + // And the members of the cycle are NOT among them: no order can fix an intra-component edge, + // so a gate that reported them would be red on a correct release. + for (const member of ["@girs/glib-2.0", "@girs/gobject-2.0", "@girs/cairo-1.0", "@girs/gjs"]) { + assert.ok(!offenders.has(member), `${member} is a cycle member and must be exempt`); + } +}); + +test("POSITIVE CONTROL: the planned order turns the gate red zero times", async () => { + const { gaps } = await replay(planPublishOrder(RECORDED_PACKAGES)); + assert.deepEqual(gaps, []); +}); + +test("the 16 packages of the incident report: 7 red replayed, 0 planned", async () => { + // The incident report counted 12, exempting only glib↔gobject. The component is six wide, so + // cairo-1.0, gio-2.0, gjs, gmodule-2.0 are exempt too β€” 12 βˆ’ 5 = 7. The difference IS the + // finding: an exemption list written by hand is five packages short of the one Tarjan finds. + const sample = new Set( + [ + "adw-1", "cairo-1.0", "freetype2-2.0", "gdk-4.0", "gdkpixbuf-2.0", "gio-2.0", "gjs", "glib-2.0", + "gmodule-2.0", "gobject-2.0", "graphene-1.0", "gsk-4.0", "gtk-4.0", "harfbuzz-0.0", "pango-1.0", + "pangocairo-1.0", + ].map(scoped), + ); + const subset = RECORDED_PACKAGES.filter((pkg) => sample.has(pkg.name)).map((pkg) => ({ + ...pkg, + dependencies: Object.fromEntries(Object.entries(pkg.dependencies).filter(([dep]) => sample.has(dep))), + })); + const plan = planPublishOrder(subset); + assert.equal((await replay(inRecordedOrder(plan))).offenders.size, 7); + assert.equal((await replay(plan)).gaps.length, 0); +}); + +test("a set that is half on the registry is caught, and the gap names the missing sibling", async () => { + const group: PlannablePackage[] = [ + { name: "@girs/adw-1", version: "4.9.0", dependencies: { "@girs/gtk-4.0": "^4.9.0", "@girs/pango-1.0": "^4.9.0" } }, + ]; + const gaps = await closureGaps(group, registryHolding(new Set(["@girs/gtk-4.0"])), satisfies); + assert.equal(gaps.length, 1); + assert.deepEqual( + { package: gaps[0].package, dependency: gaps[0].dependency, reason: gaps[0].reason }, + { package: "@girs/adw-1", dependency: "@girs/pango-1.0", reason: "absent" }, + ); + assert.match(describeGap(gaps[0]), /adw-1 declares @girs\/pango-1\.0@\^4\.9\.0/); +}); + +test("a sibling that exists at the WRONG version is a gap too, and says so differently", async () => { + // The failure a consumer sees as `notarget No matching version found` β€” the package is there, + // the version is not. Reported apart from "absent" because the two have different causes: + // one is an ordering defect, the other a partially bumped tree. + const group: PlannablePackage[] = [ + { name: "@girs/adw-1", version: "4.9.0", dependencies: { "@girs/pango-1.0": "^4.9.0" } }, + ]; + const registry: RegistryView = { async publishedVersions() { return ["4.7.0", "4.8.0"]; } }; + const gaps = await closureGaps(group, registry, satisfies); + assert.equal(gaps.length, 1); + assert.equal(gaps[0].reason, "unsatisfied"); + assert.deepEqual(gaps[0].available, ["4.7.0", "4.8.0"]); + assert.match(describeGap(gaps[0]), /none matching/); +}); + +test("edges inside a group are exempt; edges leaving it are not", async () => { + const group: PlannablePackage[] = [ + { name: "a", version: "1.0.0", dependencies: { b: "^1.0.0", outside: "^1.0.0" } }, + { name: "b", version: "1.0.0", dependencies: { a: "^1.0.0" } }, + ]; + const gaps = await closureGaps(group, registryHolding(new Set(["a", "b"])), satisfies); + assert.deepEqual( + gaps.map((gap) => gap.dependency), + ["outside"], + ); +}); + +// --- the pieces ------------------------------------------------------------------------- + +test("a two-node cycle is one group, and a self-edge does not become one", () => { + const plan = planPublishOrder([ + { name: "a", version: "1", dependencies: { b: "*" } }, + { name: "b", version: "1", dependencies: { a: "*" } }, + { name: "c", version: "1", dependencies: { c: "*", a: "*" } }, + ]); + assert.deepEqual(plan.map((g) => g.members.map((m) => m.name)), [["a", "b"], ["c"]]); +}); + +test("a dependency the release does not publish never constrains the order", () => { + // It cannot: nothing in this run publishes it. `closureGaps` still asks the registry for it, + // which is the half that would catch a sibling that was never published at all. + const plan = planPublishOrder([ + { name: "a", version: "1", dependencies: { typescript: "^5.9.2" } }, + { name: "b", version: "1", dependencies: { a: "*" } }, + ]); + assert.deepEqual(plan.map((g) => g.members.map((m) => m.name)), [["a"], ["b"]]); +}); + +test("devDependencies are not part of the order or the closure", () => { + assert.deepEqual( + runtimeDependencies({ + dependencies: { "@girs/glib-2.0": "^4.9.0" }, + devDependencies: { typescript: "*" }, + peerDependencies: { "@girs/gjs": "^4.9.0" }, + }), + { "@girs/glib-2.0": "^4.9.0", "@girs/gjs": "^4.9.0" }, + ); +}); + +test("components come back in an order that already respects the edges", () => { + const graph = new Map([ + ["leaf", new Set()], + ["mid", new Set(["leaf"])], + ["top", new Set(["mid"])], + ]); + assert.deepEqual(stronglyConnectedComponents(graph), [["leaf"], ["mid"], ["top"]]); +}); + +test("Tarjan does not overflow on a deep chain", () => { + // Recursion here would die on a graph whose depth is an input. 20 000 is well past anything + // GNOME ships and well past the default stack. + const graph = new Map>(); + for (let i = 0; i < 20_000; i++) graph.set(`n${i}`, new Set(i > 0 ? [`n${i - 1}`] : [])); + assert.equal(stronglyConnectedComponents(graph).length, 20_000); +}); diff --git a/.github/release-script/src/publish-plan.ts b/.github/release-script/src/publish-plan.ts new file mode 100644 index 0000000000..a35953f454 --- /dev/null +++ b/.github/release-script/src/publish-plan.ts @@ -0,0 +1,310 @@ +/** + * The ORDER a multi-package release goes out in, and the invariant that order exists to hold. + * + * ## The incident + * + * v4.9.0 published all 716 `@girs/*` packages in the order `readdir` handed them back, which + * is neither sorted nor topological. Measured against the registry's own `time` maps: + * `@girs/abi-3.0` went out at 22:15:33Z and `@girs/xkl-1.0` at 00:23:15Z β€” a 128-minute sweep + * in which **508 of the 716 packages were published before something they declare a dependency + * on existed**. `@girs/adw-1` was first out of the door and depends on fifteen siblings, + * `@girs/pango-1.0` among them, which appeared 96 minutes later. + * + * For those 128 minutes `npm install @girs/adw-1@4.9.0` found a package whose declared closure + * was not on the registry. gjsify's e2e legs went red twice with + * + * npm error notarget No matching version found for @girs/pango-1.0@^4.9.0 + * + * β€” an error that names neither the package the consumer asked for nor the repository the cause + * lives in. That is the expensive part: the failure surfaces in someone else's CI, an hour + * later, looking like their bug. + * + * Exact pins would not have helped a consumer tracking this release, and they cost more than + * they save β€” see `PUBLISHING.md` in ts-for-gir for the measurement. The order is the fix. + * + * ## The class + * + * "A multi-package release published in an order that is not topological." Not "pango was late". + * The two halves below are the mechanism: {@link planPublishOrder} makes the order right, and + * {@link closureGaps} proves it was right at each step β€” because an order that is correct today + * and unchecked stops being correct the first time someone changes how packages are collected. + * + * ## Cycles are real here + * + * The `@girs` graph is NOT a DAG. Tarjan over the v4.9.0 tree finds exactly one non-trivial + * strongly connected component, and it has six members: + * + * cairo-1.0 Β· gio-2.0 Β· gjs Β· glib-2.0 Β· gmodule-2.0 Β· gobject-2.0 + * + * GIR namespaces reference each other (GLib's GIR names GObject types and vice versa), so this + * is a property of the input, not a generator defect. No publish order can make a cycle + * member's closure complete at its own publish instant: whichever goes first necessarily points + * at one that is not there yet. + * + * So the unit of both halves is the GROUP, not the package: each strongly connected component + * publishes as one group, and the closure of its members is checked after the last of them, + * with the edges INSIDE the group exempt. A gate that checked per package would be red on a + * perfectly ordered release β€” and a gate that is red when the system is right gets switched off, + * which is the same failure as a gate that is always green, with the sign flipped. + * + * The components are computed, never enumerated: the next GIR set can bring a different cycle, + * and a hard-coded `glib/gobject` pair would see none of it. + */ + +/** A package as the publisher sees it: a name, a version, and what it declares it needs. */ +export interface PlannablePackage { + name: string; + version: string; + /** Every RUNTIME dependency, name β†’ range. devDependencies are not a consumer's problem. */ + dependencies: Record; +} + +/** + * One publish unit. A single package in the common case; every member of a strongly connected + * component when the graph has a cycle. + */ +export interface PublishGroup { + /** Position in the plan, 0-based. Groups publish in ascending order. */ + index: number; + members: T[]; +} + +/** A dependency that was not resolvable when the package declaring it was already published. */ +export interface ClosureGap { + /** The package whose closure is incomplete. */ + package: string; + /** The dependency that is missing or unsatisfiable. */ + dependency: string; + /** The range the package declares for it. */ + range: string; + /** Why: nothing published under that name at all, or nothing that satisfies the range. */ + reason: "absent" | "unsatisfied"; + /** The versions the registry does have, when it has the package. */ + available?: string[]; +} + +const RUNTIME_DEPENDENCY_FIELDS = ["dependencies", "peerDependencies", "optionalDependencies"] as const; + +/** + * The runtime dependencies of a raw manifest, flattened into one map. + * + * `devDependencies` are deliberately absent: they are not installed for a consumer, so they + * cannot make a published package unresolvable and they must not constrain the publish order. + * Including them would also introduce cycles that are not real β€” which is what + * `--topological-dev` warns about in the workspace tooling. + */ +export function runtimeDependencies(manifest: Record): Record { + const out: Record = {}; + for (const field of RUNTIME_DEPENDENCY_FIELDS) { + const deps = manifest[field]; + if (!deps || typeof deps !== "object") continue; + for (const [name, range] of Object.entries(deps as Record)) { + if (typeof range === "string") out[name] = range; + } + } + return out; +} + +/** + * Strongly connected components, Tarjan, iterative. + * + * Iterative rather than recursive on purpose: the depth of this graph is an input, and a + * release script that dies of a stack overflow on a deeper GIR set would fail in a way that + * says nothing about the cause. + * + * Returned in reverse topological order β€” a component appears only after every component it + * depends on, which is exactly the order a publisher wants. + */ +export function stronglyConnectedComponents(graph: Map>): string[][] { + const index = new Map(); + const low = new Map(); + const onStack = new Set(); + const stack: string[] = []; + const components: string[][] = []; + let counter = 0; + + for (const root of graph.keys()) { + if (index.has(root)) continue; + + // Each frame is a node plus how far through its neighbours we have walked. + const work: { node: string; edges: string[]; cursor: number }[] = [ + { node: root, edges: [...(graph.get(root) ?? [])], cursor: 0 }, + ]; + index.set(root, counter); + low.set(root, counter); + counter++; + stack.push(root); + onStack.add(root); + + while (work.length > 0) { + const frame = work[work.length - 1]; + if (frame.cursor < frame.edges.length) { + const next = frame.edges[frame.cursor++]; + if (!graph.has(next)) continue; // an edge out of the set constrains nothing here + if (!index.has(next)) { + index.set(next, counter); + low.set(next, counter); + counter++; + stack.push(next); + onStack.add(next); + work.push({ node: next, edges: [...(graph.get(next) ?? [])], cursor: 0 }); + } else if (onStack.has(next)) { + low.set(frame.node, Math.min(low.get(frame.node) as number, index.get(next) as number)); + } + continue; + } + + work.pop(); + const node = frame.node; + if (low.get(node) === index.get(node)) { + const component: string[] = []; + let member: string; + do { + member = stack.pop() as string; + onStack.delete(member); + component.push(member); + } while (member !== node); + components.push(component.sort()); + } + const parent = work[work.length - 1]; + if (parent) { + low.set(parent.node, Math.min(low.get(parent.node) as number, low.get(node) as number)); + } + } + } + + return components; +} + +/** + * The publish plan: every package exactly once, in groups, each group after everything it needs. + * + * Deterministic for a given input. Two runs over the same tree produce the same plan, so a + * release that has to be resumed republishes in the same order it started in. + * + * Only edges INSIDE the set constrain the order. A dependency on something this run does not + * publish cannot be sequenced by this run β€” {@link closureGaps} still checks it, which is the + * half that would catch a sibling that was never published at all. + */ +export function planPublishOrder(packages: T[]): PublishGroup[] { + const byName = new Map(packages.map((pkg) => [pkg.name, pkg])); + const graph = new Map>(); + for (const pkg of packages) { + graph.set( + pkg.name, + new Set(Object.keys(pkg.dependencies).filter((dep) => dep !== pkg.name && byName.has(dep))), + ); + } + + const components = stronglyConnectedComponents(graph); + const componentOf = new Map(); + components.forEach((component, i) => { + for (const member of component) componentOf.set(member, i); + }); + + // Condense to a DAG of components and walk it with Kahn, smallest key first. The tie-break + // is what makes the plan reproducible: Tarjan's own output order depends on which node the + // walk started at, and "reproducible" is the difference between a resumable release and a + // second, differently-ordered sweep. + const successors = components.map(() => new Set()); + const indegree = components.map(() => 0); + for (const [name, deps] of graph) { + const from = componentOf.get(name) as number; + for (const dep of deps) { + const to = componentOf.get(dep) as number; + if (to === from) continue; + // `dep` must publish BEFORE `name`: the edge in the plan runs dep β†’ name. + if (successors[to].has(from)) continue; + successors[to].add(from); + indegree[from]++; + } + } + + const key = (i: number) => components[i][0]; + const ready = components.map((_, i) => i).filter((i) => indegree[i] === 0); + ready.sort((a, b) => key(a).localeCompare(key(b))); + + const order: PublishGroup[] = []; + while (ready.length > 0) { + const current = ready.shift() as number; + order.push({ + index: order.length, + members: components[current].map((name) => byName.get(name) as T), + }); + const unlocked: number[] = []; + for (const next of successors[current]) { + if (--indegree[next] === 0) unlocked.push(next); + } + if (unlocked.length > 0) { + ready.push(...unlocked); + ready.sort((a, b) => key(a).localeCompare(key(b))); + } + } + + // Kahn terminating early means a cycle survived the condensation, which would mean Tarjan + // was wrong. Say so rather than publish a plan that silently drops packages β€” a short plan + // is a release that looks like it succeeded and left packages behind. + const planned = order.reduce((n, group) => n + group.members.length, 0); + if (planned !== packages.length) { + throw new Error( + `publish plan covers ${planned} of ${packages.length} packages β€” the component graph is still cyclic`, + ); + } + + return order; +} + +/** What the closure check is allowed to ask. Exactly one question, so a fake can answer it. */ +export interface RegistryView { + /** Versions published under `name` right now, or `null` when the registry has no such package. */ + publishedVersions(name: string): Promise; +} + +/** + * The invariant, asked of the REGISTRY rather than of our own files. + * + * After a group is published, every runtime dependency of every member must be resolvable by a + * consumer β€” which is a different question from "we published it": the registry has read + * replicas, and a package that this process uploaded is not necessarily one a `npm install` + * elsewhere can see yet. Asking our own bookkeeping would answer the question we already know + * the answer to. + * + * Edges inside `group` are exempt, and must be: see the cycle note at the top of this file. + * + * @param group the names just published together + * @param packages the manifests of those names + * @param satisfies whether a version list contains something matching a range β€” `semver.satisfies` + */ +export async function closureGaps( + group: PlannablePackage[], + registry: RegistryView, + satisfies: (version: string, range: string) => boolean, +): Promise { + const sameGroup = new Set(group.map((pkg) => pkg.name)); + const gaps: ClosureGap[] = []; + + for (const pkg of group) { + for (const [dependency, range] of Object.entries(pkg.dependencies)) { + if (sameGroup.has(dependency)) continue; + const available = await registry.publishedVersions(dependency); + if (available === null) { + gaps.push({ package: pkg.name, dependency, range, reason: "absent" }); + continue; + } + if (!available.some((version) => satisfies(version, range))) { + gaps.push({ package: pkg.name, dependency, range, reason: "unsatisfied", available }); + } + } + } + + return gaps; +} + +/** One line a human can act on: which package, which dependency, and what the registry has. */ +export function describeGap(gap: ClosureGap): string { + const have = + gap.reason === "absent" + ? "the registry has no such package" + : `the registry has ${gap.available?.length ?? 0} version(s), none matching`; + return `${gap.package} declares ${gap.dependency}@${gap.range} β€” ${have}`; +} diff --git a/.github/release-script/test/e2e.mjs b/.github/release-script/test/e2e.mjs new file mode 100644 index 0000000000..8e7a5b9d2c --- /dev/null +++ b/.github/release-script/test/e2e.mjs @@ -0,0 +1,318 @@ +/** + * The publisher, end to end, against a real npm registry that is not npmjs.org. + * + * `publish-plan.test.ts` proves the PLAN and the GATE on the recorded v4.9.0 graph. It cannot + * prove the wiring: that the plan actually decides what `npm publish` is called on, that the + * gate is reached after each group, and that a gap makes the process exit non-zero. That is what + * this does β€” a throwaway Verdaccio on localhost, a five-package tree whose alphabetical order + * is the REVERSE of its topological one, and four arms that must not all go the same way. + * + * 1 publish β†’ exits 0, and the registry's own timestamps say leaf before mid before top + * 2 publish a tree with a sibling nobody publishes β†’ exits 1 at the group that declares it + * 3 --verify-only against a HAND-MADE half-published registry β†’ exits 1, names what is missing + * 4 --verify-only against the complete set β†’ exits 0 + * + * Arm 3 is the v4.9.0 window itself, reproduced: one package on the registry naming siblings that + * are not there. Arm 4 is what stops arm 3 from being "the gate is always red". + * + * Run: npm run test:e2e (needs network once, to fetch verdaccio) + */ + +import assert from "node:assert/strict"; +import { spawn, spawnSync } from "node:child_process"; +import { createServer } from "node:net"; +import { createHash } from "node:crypto"; +import { mkdtemp, rm, writeFile } from "node:fs/promises"; +import { mkdirSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const PUBLISHER = fileURLToPath(new URL("../src/index.ts", import.meta.url)); +/** + * A port the OS just told us was free, not the Verdaccio default. + * + * 4873 is what every other Verdaccio on the machine also binds, and a stranger on that port would + * answer every request in this file with ITS storage β€” a run that looks like a result. Measured + * while writing this: an orphan from a killed run kept rejecting logins for a setting the current + * config had already fixed. The port guard below stays anyway; this only makes a collision rare. + */ +function freePort() { + return new Promise((resolve, reject) => { + const server = createServer(); + server.on("error", reject); + server.listen(0, "127.0.0.1", () => { + const { port } = server.address(); + server.close(() => resolve(port)); + }); + }); +} + +const PORT = Number(process.env.E2E_PORT ?? (await freePort())); +const REGISTRY = `http://localhost:${PORT}`; +// A fresh scope per run, so a leftover Verdaccio store can never make an arm pass by accident. +const SCOPE = `@e2e-${Date.now().toString(36)}`; +const USER = "e2e"; +const PASSWORD = "e2e-password"; + +/** Verdaccio with no uplink: every answer comes from this run, none from the internet. */ +const CONFIG = ` +storage: ./storage +auth: + htpasswd: + file: ./htpasswd + # A positive limit is what ALLOWS the PUT below to register a user; -1 disables it. + max_users: 1000 +uplinks: {} +packages: + '**': + access: $all + publish: $all + unpublish: $all +log: { type: stdout, format: pretty, level: warn } +`; + +function manifest(dir, name, dependencies) { + mkdirSync(dir, { recursive: true }); + return writeFile( + join(dir, "package.json"), + JSON.stringify({ name: `${SCOPE}/${name}`, version: "1.0.0", private: false, dependencies }, null, 2), + ); +} + +/** + * The tree. Alphabetically `a-top` comes first and depends on everything, which is exactly the + * shape that made v4.9.0 publish `@girs/adw-1` 96 minutes before `@girs/pango-1.0`. + */ +async function writeTree(root, { withGhost = false } = {}) { + const dep = (n) => ({ [`${SCOPE}/${n}`]: "^1.0.0" }); + await manifest(join(root, "a-top"), "a-top", { ...dep("b-mid"), ...dep("c-leaf") }); + await manifest(join(root, "b-mid"), "b-mid", dep("c-leaf")); + await manifest(join(root, "c-leaf"), "c-leaf", {}); + // A real cycle, so the run exercises the component grouping rather than only the DAG path. + await manifest(join(root, "cyc-x"), "cyc-x", dep("cyc-y")); + await manifest(join(root, "cyc-y"), "cyc-y", dep("cyc-x")); + if (withGhost) { + // Declares a sibling that no run publishes: the "absent" half of a broken closure. + await manifest(join(root, "d-broken"), "d-broken", dep("ghost")); + } +} + +function run(cmd, args, opts = {}) { + const result = spawnSync(cmd, args, { encoding: "utf-8", ...opts }); + return { code: result.status ?? 1, out: `${result.stdout ?? ""}${result.stderr ?? ""}` }; +} + +/** Written once Verdaccio has issued a token; every npm in this file reads it. */ +let NPMRC; + +function npmEnv(extra = {}) { + return { + ...process.env, + npm_config_userconfig: NPMRC, + NPM_REGISTRY: REGISTRY, + CI: "true", + NPM_BATCH_SIZE: "1", + NPM_BATCH_DELAY_MS: "0", + NPM_PUBLISH_DELAY_MS: "0", + // The lag budget exists for registry replicas catching up. A gap this file creates on + // purpose is permanent, so waiting the production minute for it would only make the run + // slow β€” the behaviour under test is that the budget EXPIRES and the run goes red. + NPM_CLOSURE_LAG_MS: "2000", + NPM_CLOSURE_LAG_STEP_MS: "500", + ...extra, + }; +} + +function publisher(root, extra, env = {}) { + return run( + process.execPath, + ["--experimental-strip-types", "--experimental-transform-types", "--no-warnings", PUBLISHER, ...extra], + { cwd: root, env: npmEnv(env) }, + ); +} + +/** + * Register a user and keep the token Verdaccio hands back. + * + * `publish: $all` is not enough on its own: the npm CLI refuses with ENEEDAUTH before it ever + * asks the registry, so the e2e needs a real credential rather than an open registry. + */ +async function authenticate(dir) { + // Basic auth, because the user already exists in the seeded htpasswd file: without it + // Verdaccio reads the same PUT as a REGISTRATION and answers 409. + const basic = Buffer.from(`${USER}:${PASSWORD}`).toString("base64"); + const response = await fetch(`${REGISTRY}/-/user/org.couchdb.user:${USER}`, { + method: "PUT", + headers: { "content-type": "application/json", authorization: `Basic ${basic}` }, + body: JSON.stringify({ name: USER, password: PASSWORD, type: "user" }), + }); + const body = await response.json(); + if (!body.token) throw new Error(`verdaccio issued no token: ${response.status} ${JSON.stringify(body)}`); + NPMRC = join(dir, ".npmrc"); + await writeFile(NPMRC, `registry=${REGISTRY}/\n//localhost:${PORT}/:_authToken=${body.token}\n`); + return body.token; +} + +/** When each version reached the registry, as the REGISTRY reports it β€” not as we remember it. */ +async function publishedAt(name) { + const response = await fetch(`${REGISTRY}/${encodeURIComponent(`${SCOPE}/${name}`)}`); + if (!response.ok) return null; + const packument = await response.json(); + return Date.parse(packument.time?.["1.0.0"] ?? 0) || null; +} + +async function startVerdaccio(dir) { + // A leftover Verdaccio on this port would answer every request in this file with ITS config + // and ITS storage, and the run would look like a result. Measured while writing this: a + // server from an earlier attempt kept rejecting logins for a setting the current config had + // already fixed. Refuse the port rather than inherit a stranger. + try { + await fetch(`${REGISTRY}/-/ping`, { signal: AbortSignal.timeout(1000) }); + throw new Error(`something is already listening on ${REGISTRY} β€” stop it, or set E2E_PORT`); + } catch (error) { + if (error instanceof Error && error.message.includes("already listening")) throw error; + } + + await writeFile(join(dir, "config.yaml"), CONFIG); + // The user is seeded into the htpasswd file rather than registered over HTTP: Verdaccio 6 + // answers `PUT /-/user/...` for an unknown name with "user registration disabled" regardless + // of `max_users`, and an e2e that needs a flag flipped on the server is an e2e that will + // break on the next Verdaccio. `{SHA}` is base64(sha1(password)), the Apache htpasswd form. + const digest = createHash("sha1").update(PASSWORD).digest("base64"); + await writeFile(join(dir, "htpasswd"), `${USER}:{SHA}${digest}\n`); + // Its own process group, so the teardown below can take the `npx` wrapper AND the server it + // spawned. Killing only the wrapper leaves a Verdaccio holding the port β€” which is how the + // orphan that made the port guard necessary came to exist. + const proc = spawn("npx", ["--yes", "verdaccio@6", "--config", join(dir, "config.yaml"), "--listen", String(PORT)], { + cwd: dir, + stdio: ["ignore", "pipe", "pipe"], + detached: true, + }); + const teardown = () => { + try { + process.kill(-proc.pid, "SIGKILL"); + } catch { + /* already gone */ + } + }; + proc.teardown = teardown; + process.on("exit", teardown); + for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) process.on(signal, () => process.exit(1)); + proc.stdout.on("data", () => {}); + proc.stderr.on("data", () => {}); + + for (let attempt = 0; attempt < 120; attempt++) { + try { + const response = await fetch(`${REGISTRY}/-/ping`, { signal: AbortSignal.timeout(1000) }); + if (response.ok || response.status === 404) return proc; + } catch { + /* not up yet */ + } + await new Promise((resolve) => setTimeout(resolve, 500)); + } + teardown(); + throw new Error("verdaccio did not come up within 60s"); +} + +const work = await mkdtemp(join(tmpdir(), "release-e2e-")); +let verdaccio; +let failures = 0; + +const arm = (name, fn) => { + try { + const result = fn(); + return Promise.resolve(result).then( + () => console.log(`βœ” ${name}`), + (error) => { + failures++; + console.error(`βœ– ${name}\n ${error?.message ?? error}`); + }, + ); + } catch (error) { + failures++; + console.error(`βœ– ${name}\n ${error?.message ?? error}`); + return Promise.resolve(); + } +}; + +try { + verdaccio = await startVerdaccio(work); + const token = await authenticate(work); + console.log(`verdaccio up on ${REGISTRY}, scope ${SCOPE}`); + + // --- arm 1: the plan decides the order, and the registry agrees ------------------------- + const good = join(work, "good"); + await writeTree(good); + const published = publisher(good, [], { NODE_AUTH_TOKEN: token }); + + await arm("a tree whose alphabetical order is wrong publishes and exits 0", async () => { + assert.equal(published.code, 0, published.out.slice(-2000)); + assert.match(published.out, /1 of them a dependency cycle/); + }); + + await arm("the registry's own timestamps say leaf, then mid, then top", async () => { + const [leaf, mid, top] = await Promise.all([publishedAt("c-leaf"), publishedAt("b-mid"), publishedAt("a-top")]); + assert.ok(leaf && mid && top, `not everything published: ${JSON.stringify({ leaf, mid, top })}`); + assert.ok(leaf <= mid, `c-leaf (${leaf}) must not follow b-mid (${mid})`); + assert.ok(mid <= top, `b-mid (${mid}) must not follow a-top (${top})`); + }); + + await arm("both members of the cycle are published, as one group", async () => { + assert.ok(await publishedAt("cyc-x")); + assert.ok(await publishedAt("cyc-y")); + }); + + // --- arm 2: a sibling nobody publishes stops the sweep ---------------------------------- + await arm("NEGATIVE: a package declaring an unpublished sibling exits 1 and names it", async () => { + const broken = join(work, "broken"); + await writeTree(broken, { withGhost: true }); + const result = publisher(broken, [], { NODE_AUTH_TOKEN: token }); + assert.equal(result.code, 1, `expected a red run, got 0:\n${result.out.slice(-2000)}`); + assert.match(result.out, /Incomplete closure/); + assert.match(result.out, /ghost/); + }); + + // --- arm 3: the v4.9.0 window, reproduced by hand --------------------------------------- + await arm("NEGATIVE: --verify-only is red on a half-published set, and says what is missing", async () => { + const half = join(work, "half"); + const scope = `${SCOPE}-half`; + mkdirSync(join(half, "a-top"), { recursive: true }); + mkdirSync(join(half, "c-leaf"), { recursive: true }); + await writeFile( + join(half, "a-top", "package.json"), + JSON.stringify({ name: `${scope}/a-top`, version: "1.0.0", dependencies: { [`${scope}/c-leaf`]: "^1.0.0" } }), + ); + await writeFile( + join(half, "c-leaf", "package.json"), + JSON.stringify({ name: `${scope}/c-leaf`, version: "1.0.0" }), + ); + // Publish ONLY the dependent β€” exactly what the registry held between 22:17Z and 23:53Z. + const pushed = run("npm", ["publish", "--registry", REGISTRY, "--access", "public"], { + cwd: join(half, "a-top"), + env: npmEnv(), + }); + assert.equal(pushed.code, 0, pushed.out.slice(-1500)); + + const result = publisher(half, ["--verify-only"]); + assert.equal(result.code, 1, `expected a red run, got 0:\n${result.out.slice(-2000)}`); + assert.match(result.out, /Incomplete closure/); + assert.match(result.out, /c-leaf/); + }); + + // --- arm 4: and green once the set is whole --------------------------------------------- + await arm("POSITIVE: --verify-only is green on the complete set", async () => { + const result = publisher(good, ["--verify-only"]); + assert.equal(result.code, 0, result.out.slice(-2000)); + assert.match(result.out, /every published package resolves/); + }); +} finally { + verdaccio?.teardown?.(); + await rm(work, { recursive: true, force: true }); +} + +if (failures > 0) { + console.error(`\n${failures} arm(s) failed`); + process.exit(1); +} +console.log("\nall arms behaved as they must"); diff --git a/.github/release-script/tsconfig.json b/.github/release-script/tsconfig.json index 9fda6b2355..22edd52336 100644 --- a/.github/release-script/tsconfig.json +++ b/.github/release-script/tsconfig.json @@ -5,6 +5,7 @@ "strict": true, "rootDir": "src", "verbatimModuleSyntax": true, + "allowImportingTsExtensions": true, "noEmit": true }, "include": ["src/**/*.ts"] diff --git a/.github/workflows/release-script.yml b/.github/workflows/release-script.yml new file mode 100644 index 0000000000..0fab04fdbc --- /dev/null +++ b/.github/workflows/release-script.yml @@ -0,0 +1,63 @@ +# The publisher, checked BEFORE it publishes. +# +# Until now nothing in this repository ran on a pull request: `release.yml` fires on push to main +# and `sdk-types.yml` on a dispatch or a schedule, so the script that pushes 716 packages to npm +# was first executed by the release it was meant to make. A type error, a broken ordering, a gate +# that no longer goes red β€” all of it surfaced mid-sweep, with part of the set already public. +# +# This runs the same three things a maintainer would: the type check, the plan and gate tests +# against the recorded v4.9.0 graph, and the end-to-end sweep against a throwaway Verdaccio. +name: Release Script + +on: + pull_request: + paths: + - ".github/release-script/**" + - ".github/workflows/release-script.yml" + push: + branches: [main] + paths: + - ".github/release-script/**" + - ".github/workflows/release-script.yml" + workflow_dispatch: + +concurrency: + group: release-script-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + check: + name: Check, test, publish end to end + runs-on: ubuntu-24.04 + timeout-minutes: 20 + defaults: + run: + working-directory: .github/release-script + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-node@v7 + with: + node-version: 24.x + package-manager-cache: false + + - run: npm ci + + - name: Type-check + run: npm run check + + # The plan and the closure gate, replayed over the recorded v4.9.0 release: 508 red in the + # order it actually went out, 0 in the order the planner produces. Both arms, because a + # gate that is green on both is measuring the end state, and one that is red on both does + # not distinguish sorted from unsorted. + - name: Unit tests + run: npm test + + # The wiring: that the plan decides what `npm publish` is called on, that the gate is + # reached after each group, and that a gap makes the process exit non-zero. Against a real + # registry on localhost, so no arm can pass because a stub was too agreeable. + - name: End-to-end against a local registry + run: npm run test:e2e diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fe27d45285..60b3d8dde5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -60,14 +60,24 @@ jobs: npm --version # The publisher is TypeScript executed with type STRIPPING, which does no - # checking whatsoever β€” so a type error in the script that publishes 703 + # checking whatsoever β€” so a type error in the script that publishes 716 # packages would first surface at release time, halfway through a sweep. # The package has had a `check` script all along; nothing ran it. - - name: Type-check the release script + # + # `npm ci` is also what puts `semver` on disk for the publish step below: the + # closure gate asks whether a declared RANGE is satisfiable, and reimplementing + # that would be a second truth about the one question npm already answers. + # + # `npm test` runs the plan and the gate against the recorded v4.9.0 graph, + # including the arm that must be RED β€” see publish-plan.test.ts. It is on the + # critical path on purpose: a publisher whose ordering is broken should never + # reach the first `npm publish`. + - name: Check and test the release script working-directory: .github/release-script run: | npm ci npm run check + npm test # Both auth paths stay supported, and the token decides which one runs. # diff --git a/.github/workflows/sdk-types.yml b/.github/workflows/sdk-types.yml index 622ddebf85..dbc8698edc 100644 --- a/.github/workflows/sdk-types.yml +++ b/.github/workflows/sdk-types.yml @@ -264,12 +264,17 @@ jobs: console.log(`${manifest.name}@${manifest.version}: ${subpaths.length} subpaths`); ' "$manifest" '${{ matrix.channel.package }}' '${{ steps.channel_plan.outputs.version }}' '${{ steps.sdk.outputs.commit }}' - - name: Type-check the release script - if: steps.channel_plan.outputs.rebuild == 'true' && !inputs.dry_run + # NOT gated on `dry_run`: `npm ci` is what puts `semver` on disk, and the publisher + # imports it whether or not it ends up publishing. Gating the install on the run being + # real made a dry run fail on a missing module β€” a failure about the harness, not about + # the channel it was asked to check. + - name: Check and test the release script + if: steps.channel_plan.outputs.rebuild == 'true' working-directory: .github/release-script run: | npm ci npm run check + npm test # Same publisher as release.yml, pointed at `sdk/` β€” including its retry policy and its # refusal to treat "this version already exists" as success. From 464b5b03e1b29572a3dc812451b9056382a9d701 Mon Sep 17 00:00:00 2001 From: Pascal Garber Date: Fri, 11 Sep 2026 09:00:28 +0200 Subject: [PATCH 2/3] refactor: test the batcher, retry the gate's reads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two gaps in the previous commit, both of the kind that only show up under a condition CI does not produce by itself. `takeIndependentRun` decides whether the pacing knob may put two groups in one batch, and it lived in index.ts where nothing could reach it. Both call sites run at batch=1, so a bug in it would have waited for the day somebody raised the knob. Moved into publish-plan.ts with three controls, one of them over the whole recorded release: no batch ever contains a dependency of its own members. The gate's registry reads threw straight out of the run on any non-404 error. A single 503 in a two-hour sweep would have failed the release as an incomplete closure β€” the one diagnosis that sends someone looking in the wrong repository. Retried on a transient status now, like every other registry read in this file. Claude-Session: https://claude.ai/code/session_01N4yEeHoGMC4pvbkqxMsYfj --- .github/release-script/src/index.ts | 62 +++++++++---------- .../release-script/src/publish-plan.test.ts | 46 ++++++++++++++ .github/release-script/src/publish-plan.ts | 32 ++++++++++ 3 files changed, 108 insertions(+), 32 deletions(-) diff --git a/.github/release-script/src/index.ts b/.github/release-script/src/index.ts index ed19246d9a..7f2e12e673 100644 --- a/.github/release-script/src/index.ts +++ b/.github/release-script/src/index.ts @@ -12,6 +12,7 @@ import { type PublishGroup, type RegistryView, runtimeDependencies, + takeIndependentRun, } from "./publish-plan.ts"; // Configuration and types @@ -936,16 +937,36 @@ class LiveRegistry implements RegistryView { const cached = this.known.get(name); if (cached) return cached; - const response = await fetch(getApiUrl(this.registry, name), { - headers: { Accept: "application/json", "User-Agent": "ts-for-gir-release-script/1.0.0" }, - signal: AbortSignal.timeout(API_TIMEOUT_MS), - }); - if (response.status === 404) return null; - if (!response.ok) throw new HttpStatusError(response.status, `Registry responded with ${response.status}`); + // Retried on a transient status, like every other registry read here. Without it a single + // 503 in the middle of a two-hour sweep would fail the run as an ordering defect β€” the one + // diagnosis that would send someone looking in the wrong place. + const versions = await withRetry( + async () => { + const response = await fetch(getApiUrl(this.registry, name), { + headers: { Accept: "application/json", "User-Agent": "ts-for-gir-release-script/1.0.0" }, + signal: AbortSignal.timeout(API_TIMEOUT_MS), + }); + if (response.status === 404) return null; + if (!response.ok) { + if (isRetryableHttpStatus(response.status)) { + throw new HttpStatusError(response.status, `Registry responded with ${response.status}`); + } + return null; + } + const data = (await response.json()) as { versions?: Record }; + const found = Object.keys(data.versions ?? {}); + return found.length === 0 ? null : found; + }, + { + label: `closure:${name}`, + maxRetries: MAX_RETRIES_STATUS, + baseDelayMs: RETRY_BASE_MS, + maxDelayMs: RETRY_MAX_MS, + shouldRetry: (err) => isHttpStatusError(err) && isRetryableHttpStatus(err.status), + }, + ); - const data = (await response.json()) as { versions?: Record }; - const versions = Object.keys(data.versions ?? {}); - if (versions.length === 0) return null; + if (versions === null) return null; this.known.set(name, versions); return versions; } @@ -1005,29 +1026,6 @@ async function verifyGroupClosure( return gaps; } -/** - * The next run of groups that can go out together: consecutive in the plan AND independent of - * one another. - * - * `NPM_BATCH_SIZE` is a PACING knob (batch=1 in release.yml, because concurrent provenance - * signing draws E429), not a licence to publish a dependent beside its dependency. Checking - * independence is what lets the knob keep its old meaning without reintroducing the defect. - */ -function takeIndependentRun(plan: PublishGroup[], from: number, max: number): PublishGroup[] { - const run: PublishGroup[] = [plan[from]]; - const inRun = new Set(plan[from].members.map((member) => member.name)); - for (let i = from + 1; i < plan.length && run.length < max; i++) { - const candidate = plan[i]; - const dependsOnRun = candidate.members.some((member) => - Object.keys(member.dependencies).some((dep) => inRun.has(dep)), - ); - if (dependsOnRun) break; - run.push(candidate); - for (const member of candidate.members) inRun.add(member.name); - } - return run; -} - // Phase 2: Publish what needs publishing, in topological order, checking the closure as we go async function publishPendingPackages( packages: Package[], diff --git a/.github/release-script/src/publish-plan.test.ts b/.github/release-script/src/publish-plan.test.ts index ae25f0af03..955042a56e 100644 --- a/.github/release-script/src/publish-plan.test.ts +++ b/.github/release-script/src/publish-plan.test.ts @@ -34,6 +34,7 @@ import { type RegistryView, runtimeDependencies, stronglyConnectedComponents, + takeIndependentRun, } from "./publish-plan.ts"; // --- the recorded release --------------------------------------------------------------- @@ -274,3 +275,48 @@ test("Tarjan does not overflow on a deep chain", () => { for (let i = 0; i < 20_000; i++) graph.set(`n${i}`, new Set(i > 0 ? [`n${i - 1}`] : [])); assert.equal(stronglyConnectedComponents(graph).length, 20_000); }); + +// --- batching ----------------------------------------------------------------------------- + +test("a batch never carries a group beside one it depends on", () => { + // The pacing knob must not be able to undo the plan. Two independent leaves batch; the + // dependent that follows them does not join, however much room the batch has left. + const plan = planPublishOrder([ + { name: "leaf-a", version: "1", dependencies: {} }, + { name: "leaf-b", version: "1", dependencies: {} }, + { name: "top", version: "1", dependencies: { "leaf-a": "*", "leaf-b": "*" } }, + ]); + assert.deepEqual( + takeIndependentRun(plan, 0, 5).map((group) => group.members.map((m) => m.name)), + [["leaf-a"], ["leaf-b"]], + ); + assert.deepEqual( + takeIndependentRun(plan, 2, 5).map((group) => group.members.map((m) => m.name)), + [["top"]], + ); +}); + +test("a batch size of one is one group, independent or not", () => { + const plan = planPublishOrder([ + { name: "leaf-a", version: "1", dependencies: {} }, + { name: "leaf-b", version: "1", dependencies: {} }, + ]); + assert.equal(takeIndependentRun(plan, 0, 1).length, 1); +}); + +test("over the real release, no batch ever contains a dependency of its own members", () => { + const plan = planPublishOrder(RECORDED_PACKAGES); + for (let i = 0; i < plan.length; ) { + const run = takeIndependentRun(plan, i, 5); + const inRun = new Set(run.flatMap((group) => group.members.map((m) => m.name))); + for (const group of run) { + for (const member of group.members) { + for (const dep of Object.keys(member.dependencies)) { + const sameGroup = group.members.some((m) => m.name === dep); + assert.ok(!inRun.has(dep) || sameGroup, `${member.name} batched beside its dependency ${dep}`); + } + } + } + i += run.length; + } +}); diff --git a/.github/release-script/src/publish-plan.ts b/.github/release-script/src/publish-plan.ts index a35953f454..1e9466d9ca 100644 --- a/.github/release-script/src/publish-plan.ts +++ b/.github/release-script/src/publish-plan.ts @@ -254,6 +254,38 @@ export function planPublishOrder(packages: T[]): Pub return order; } +/** + * The next run of groups that can go out together: consecutive in the plan AND independent of + * one another. + * + * A publisher's batch size is a PACING knob β€” release.yml runs at 1, because concurrent + * provenance signing draws E429 β€” and never a licence to publish a dependent beside its + * dependency. Checking independence is what lets the knob keep its old meaning without + * reintroducing the defect the plan exists to remove. + * + * Consecutive only: it stops at the first group that depends on the run so far rather than + * scanning ahead for another independent one, because reordering past a dependent would make the + * publish order differ from the plan, and the plan is what the closure gate is checked against. + */ +export function takeIndependentRun( + plan: PublishGroup[], + from: number, + max: number, +): PublishGroup[] { + const run: PublishGroup[] = [plan[from]]; + const inRun = new Set(plan[from].members.map((member) => member.name)); + for (let i = from + 1; i < plan.length && run.length < max; i++) { + const candidate = plan[i]; + const dependsOnRun = candidate.members.some((member) => + Object.keys(member.dependencies).some((dep) => inRun.has(dep)), + ); + if (dependsOnRun) break; + run.push(candidate); + for (const member of candidate.members) inRun.add(member.name); + } + return run; +} + /** What the closure check is allowed to ask. Exactly one question, so a fake can answer it. */ export interface RegistryView { /** Versions published under `name` right now, or `null` when the registry has no such package. */ From dd42db44879de690acb3c57c02a062d1865c25ad Mon Sep 17 00:00:00 2001 From: Pascal Garber Date: Fri, 11 Sep 2026 09:02:54 +0200 Subject: [PATCH 3/3] fix: make the batch size cap concurrency, not groups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two knobs that meant less than they read. `NPM_BATCH_SIZE` limited how many GROUPS were taken and then published every member of them at once. A group is one package almost everywhere, so that looked the same β€” except on the six-member cycle, which is the first group out and would have published six packages concurrently under `batch=1`. release.yml runs at 1 because concurrent provenance signing draws E429, so the one group that ignored the setting was the one where it matters most. `pMap` now caps the publishes themselves. `NPM_TIMEOUT_SEC` is a per-publish budget and the final install probe was using it. Measured: 5.5 minutes for 716 packages on a cold cache against a 300 s default, so a run that did not override it would have timed out and reported an installable release as uninstallable. Also: a failed publish now stops the sweep AFTER the batch instead of whichever concurrent rejection won the race, so the error names every package that failed rather than one of them. Claude-Session: https://claude.ai/code/session_01N4yEeHoGMC4pvbkqxMsYfj --- .github/release-script/src/index.ts | 58 ++++++++++++++++------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/.github/release-script/src/index.ts b/.github/release-script/src/index.ts index 7f2e12e673..4a35334e44 100644 --- a/.github/release-script/src/index.ts +++ b/.github/release-script/src/index.ts @@ -1073,50 +1073,52 @@ async function publishPendingPackages( for (let i = 0; i < pendingGroups.length; ) { const run = takeIndependentRun(pendingGroups, i, BATCH_SIZE); - const batch = run.flatMap((group) => group.members); + const members = run.flatMap((group) => group.members); i += run.length; - console.log(`πŸ“¦ Groups ${run[0].index}…${run[run.length - 1].index} (${batch.map((p) => p.name).join(", ")})`); + console.log(`πŸ“¦ Groups ${run[0].index}…${run[run.length - 1].index} (${members.map((p) => p.name).join(", ")})`); - const batchResults = await Promise.allSettled( - batch.map(async (pkg): Promise => { + // `BATCH_SIZE` caps CONCURRENCY, not merely how many groups are taken. A group can hold + // more than one package β€” the six-member cycle does β€” and publishing a whole group at once + // would ignore the operator's pacing on exactly the group where it is least wanted: + // release.yml runs at 1 because concurrent provenance signing draws E429. + const batchResults = await pMap( + members, + async (pkg): Promise => { + const action = statuses.get(pkg.name)?.exists ? "update" : "create"; try { - const action = statuses.get(pkg.name)?.exists ? "update" : "create"; - if (config.dryRun) { console.log(`πŸ“¦ [DRY RUN] Would ${action} ${pkg.name}@${pkg.version}`); return { result: `dry-run-${action}` as ProcessResult, pkg }; } - await publishPackageWithRetry(pkg, config); return { result: action === "update" ? "updated" : "created", pkg }; } catch (error) { const message = error instanceof Error ? error.message : "Unknown error"; console.error(`❌ ${pkg.name}: ${message}`); - - if (config.continueOnError) { - return { result: "error", pkg, error: message }; - } - throw error; + return { result: "error", pkg, error: message }; } - }), + }, + BATCH_SIZE, ); + const failed: BatchResult[] = []; for (const result of batchResults) { - if (result.status === "fulfilled") { - if (result.value.result === "error") { - errors++; - } else { - processed++; - published.push(result.value.pkg); - registry.invalidate(result.value.pkg.name); - } - } else if (config.continueOnError) { - console.error(`❌ Batch error: ${result.reason}`); + if (result.result === "error") { errors++; - } else { - throw result.reason; + failed.push(result); + continue; } + processed++; + published.push(result.pkg); + registry.invalidate(result.pkg.name); + } + + // Without `--continue-on-error` a failed publish stops the sweep β€” after the batch rather + // than mid-flight, so the log says which of the concurrent publishes failed instead of + // whichever lost the race to reject first. + if (failed.length > 0 && !config.continueOnError) { + throw new Error(`${failed.map((f) => `${f.pkg.name}: ${f.error}`).join("; ")}`); } // The gate. A dry run publishes nothing, so there is nothing yet for a consumer to resolve @@ -1179,10 +1181,14 @@ async function verifyInstallableClosure(packages: Package[], config: Config): Pr ), ); + // Its own budget, not the per-publish one. Measured: 5.5 minutes for 716 packages on a cold + // cache, against a 300 s default β€” so the probe would have timed out and reported the + // release as uninstallable on the first run that used the default. + const timeoutSec = Math.max(config.timeoutSec, 15 * 60); const { code, output } = await runNpm( ["install", "--no-package-lock", "--no-audit", "--no-fund", "--ignore-scripts", "--registry", config.registry], dir, - config.timeoutSec, + timeoutSec, ); if (code !== 0) {