Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/sync-icon-sets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ jobs:
# the first run after a merge passed and every run after it failed.
git fetch origin "+refs/heads/$BRANCH:refs/remotes/origin/$BRANCH" || true
git checkout -B "$BRANCH"
git add icon-sets.json
# The sync sets docs/installation.md's pack-table counts from the catalogue too.
git add icon-sets.json docs/installation.md
git commit -m 'docs: sync icon-sets catalog' || true
# Lease kept rather than dropped for --force: it still refuses to clobber a
# push that arrived after the fetch above, which is the case it exists for.
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ All notable changes to `ichava/core` follow [Keep a Changelog](https://keepachan

### Fixed

- **The nightly catalogue sync updates the installation guide's pack table with the catalogue.** `bin/sync-icon-sets.php` rewrote `icon-sets.json` alone, so a count change opened a pull request that `InstallationPackTableTest` failed: #179 moved tabler to 6,287 and openmoji to 8,990 while `docs/installation.md` still said 6,257 and 8,568. After writing the catalogue, the script now sets each table row's count from it with `withPackTableCounts()`, and the workflow commits both files. Rows, order and repositories are left as written, so a set added or removed still fails the table test. `tests/Unit/SyncIconSetsDocTableTest.php` covers it (proven red by leaving the counts alone).
- **The nightly catalogue sync no longer puts Twemoji's pre-split values back.** `bin/sync-icon-sets.php` reads each pack at its latest tag, and `icon-sets-twemoji`'s `v0.1.0` still holds OpenMoji, so #176 proposed 10,567 "Emoji Sets" over the recorded 3,435 "Twemoji". A set in `icon-sets.json` may now carry a `hold` (`tag`, `commit`, `reason`): while that tag is the latest release at that commit the sync keeps the set's snapshot, and the hold drops itself once a newer tag is cut or the tag moves. The twemoji set is held at `v0.1.0`. `tests/Unit/SyncIconSetsHoldTest.php` covers it (proven red by ignoring the commit).
- **A pack listed with the application boots again.** `PackConfigCache` resolved the cache store when it was built, and a pack's constants class builds it while the providers are still registering, before the store exists, so every pack failed to boot with `Target class [cache] does not exist` (found running the packs against #172). The store is now resolved when it is used. Core's own pack tests registered their fixture after boot, which is why none saw it; `tests/Feature/PackBootsInProviderListTest.php` lists the fixture with the application.
- **`InformationService::discoverPackages()` finds the installed packs.** It globbed `vendor/*/ichava-*`, which matches no pack (packs install as `vendor/ichava/icon-sets-*`), and reported `registered` through `IconRegistry::has()`, which looks up an icon, not a package, so `ichava::ichava-core.info discover` listed nothing. It now asks `Composer\InstalledVersions` for every package of type `ichava-icon-set` and reports `registered` through `IconRegistry::isRegistered()`. The signature and return shape are unchanged. A pack is identified by its composer type and nothing else (owner, 2026-11-05): the `vendor/*/ichava-*` directory glob is removed, since no pack in the estate matched it, and the `platform/ichava` scan now keeps only a directory whose composer.json declares `ichava-icon-set`, keyed by that file's `name` instead of `ichava/<directory>`. A checkout there without the type is no longer listed. `tests/Feature/InstalledPackDiscoveryTest.php`.
Expand Down
43 changes: 41 additions & 2 deletions bin/sync-icon-sets.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@

// Run only when executed as a script, so the functions below can be loaded and tested on their own.
if (realpath((string) ($_SERVER['SCRIPT_FILENAME'] ?? '')) === __FILE__) {
exit(main(dirname(__DIR__) . '/icon-sets.json'));
exit(main(dirname(__DIR__) . '/icon-sets.json', dirname(__DIR__) . '/docs/installation.md'));
}

function main(string $manifestPath): int
function main(string $manifestPath, ?string $docPath = null): int
{
$raw = @file_get_contents($manifestPath);

Expand Down Expand Up @@ -113,9 +113,48 @@ function main(string $manifestPath): int
file_put_contents($manifestPath, $encoded . "\n");
echo "Wrote {$manifestPath}\n";

// docs/installation.md shows each set's count, and InstallationPackTableTest fails when it
// disagrees with the catalogue. Writing the catalogue alone opened a pull request that
// could never go green (core#179), so the table moves with it.
if ($docPath !== null && is_file($docPath)) {
$doc = (string) file_get_contents($docPath);
$updated = withPackTableCounts($doc, $manifest['sets']);

if ($updated !== $doc) {
file_put_contents($docPath, $updated);
echo "Wrote {$docPath}\n";
}
}

return 0;
}

/**
* The installation guide with each pack-table row's count set from the catalogue.
*
* Only the count cell of a row whose package is in the catalogue changes; rows, order and
* repositories are left as written, so a set added or removed still fails the table test
* rather than being papered over here.
*
* @param list<array<string, mixed>> $sets
*/
function withPackTableCounts(string $doc, array $sets): string
{
$counts = [];

foreach ($sets as $set) {
if (isset($set['package'], $set['icon_count']) && is_int($set['icon_count'])) {
$counts[(string) $set['package']] = number_format($set['icon_count']);
}
}

return (string) preg_replace_callback(
'/^(\| `(ichava\/[\w-]+)` \| )([^|]+?)( \| `https:\/\/github\.com\/[\w\/.-]+` \|)$/m',
static fn (array $m): string => isset($counts[$m[2]]) ? $m[1] . $counts[$m[2]] . $m[4] : $m[0],
$doc,
);
}

/**
* The catalogue without its sync timestamp, for comparing two runs.
*
Expand Down
42 changes: 42 additions & 0 deletions tests/Unit/SyncIconSetsDocTableTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

// bin/sync-icon-sets.php rewrote icon-sets.json alone, so a count change opened a
// pull request that InstallationPackTableTest failed (core#179: tabler 6,257 -> 6,287,
// openmoji 8,568 -> 8,990). The sync now sets the guide's count cells from the
// catalogue it writes.

require_once dirname(__DIR__, 2) . '/bin/sync-icon-sets.php';

function docTable(string $tabler, string $openmoji): string
{
return "Intro.\n\n| Package | Icons | Repository |\n|---|---|---|\n"
. "| `ichava/icon-sets-tabler` | {$tabler} | `https://github.com/ichava/icon-sets-tabler` |\n"
. "| `ichava/icon-sets-openmoji` | {$openmoji} | `https://github.com/ichava/icon-sets-openmoji` |\n"
. "\nOutro mentions 6,257 icons.\n";
}

it('sets each row count from the catalogue', function () {
$sets = [
['package' => 'ichava/icon-sets-tabler', 'icon_count' => 6287],
['package' => 'ichava/icon-sets-openmoji', 'icon_count' => 8990],
];

expect(withPackTableCounts(docTable('6,257', '8,568'), $sets))->toBe(docTable('6,287', '8,990'));
});

it('leaves a row the catalogue does not name, and the prose around the table', function () {
$doc = docTable('6,257', '8,568');

expect(withPackTableCounts($doc, [['package' => 'ichava/icon-sets-tabler', 'icon_count' => 6257]]))->toBe($doc)
->and(withPackTableCounts($doc, []))->toBe($doc);
});

it('keeps the real guide in step with the real catalogue', function () {
$root = dirname(__DIR__, 2);
$sets = json_decode((string) file_get_contents($root . '/icon-sets.json'), true, flags: JSON_THROW_ON_ERROR)['sets'];
$doc = (string) file_get_contents($root . '/docs/installation.md');

expect(withPackTableCounts($doc, $sets))->toBe($doc);
});
Loading