diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 98a1e83..fa9ae43 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,8 +1,8 @@ name: Refresh readme.md on: schedule: - # Run every 4 hours on the hour (UTC). - - cron: '0 */4 * * *' + # Run once daily at 00:00 UTC. + - cron: '0 0 * * *' workflow_dispatch: {} jobs: refresh: diff --git a/libraries.yml b/libraries.yml index 7090e2a..7ac7014 100644 --- a/libraries.yml +++ b/libraries.yml @@ -1,56 +1,248 @@ +categories: + - name: Data Types + description: > + Modules that extend Valkey/Redis with new native data types, + such as JSON, protobuf, Roaring Bitmaps, interval sets, + and enhanced Hash/String/ZSet variants. + - name: Search & Indexing + description: > + Full-text search, vector similarity search, secondary indexing, + and image similarity modules that add query capabilities beyond + the built-in Valkey/Redis commands. + - name: Probabilistic Data Structures + description: > + Memory-efficient approximate data structures including Bloom and + Cuckoo filters, Count-Min Sketch, Top-K, t-digest, and + Apache DataSketches integration. + - name: AI & Programmability + description: > + In-database machine-learning inference, LLM integration, + neural-network data types, and programmable scripting engines + that run user-defined logic inside Valkey/Redis. + - name: Infrastructure & Utilities + description: > + Rate limiters, authentication modules, consensus protocols, + time-series engines, distributed locks, timers, ID generators, + and other infrastructure building blocks. + libraries: - url: https://github.com/tzongw/redis-timer.git + description: "In-process Lua script scheduler supporting periodic and one-shot timers." + tags: [utility] + category: Infrastructure & Utilities - url: https://github.com/f0rmiga/sessiongate.git + description: "HTTP session management backed by Redis with pluggable storage backends." + tags: [utility] + category: Infrastructure & Utilities - url: https://github.com/aviggiano/redis-roaring.git + description: "Compressed Roaring Bitmap commands powered by CRoaring." + tags: [datatype] + category: Data Types - url: https://github.com/TamarLabs/ReDe.git + description: "Lawn-based data dehydrator managing millions of deferred elements with timed replay." + tags: [timeseries] + category: Infrastructure & Utilities - url: https://github.com/erans/redissnowflake.git + description: "Twitter Snowflake-style 64-bit unique time-ordered ID generation." + tags: [id] + category: Infrastructure & Utilities - url: https://github.com/usmanm/redis-tdigest.git + description: "Online quantile and CDF estimation via merging t-digest sketches." + tags: [probabilistic] + category: Probabilistic Data Structures - url: https://github.com/sklivvz/cthulhu.git + description: "Embed pre-compiled JavaScript extensions via duktape for custom commands." + tags: [programmable] + category: AI & Programmability - url: https://github.com/antirez/neural-redis.git + description: "Feed-forward neural network as a native data type with inline training and inference." + tags: [ai] + category: AI & Programmability - url: https://github.com/brandur/redis-cell.git + description: "Single-command rate limiter using the GCRA algorithm." + tags: [ratelimit] + category: Infrastructure & Utilities - url: https://github.com/RedisGears/RedisGears.git + description: "Programmable execution engine running JavaScript functions and triggers inside Redis." + tags: [programmable] + category: AI & Programmability - url: https://github.com/RedisAI/RedisAI.git + description: "In-Redis deep-learning / ML model inference workload runner (archived)." + tags: [ai] + category: AI & Programmability - url: https://github.com/RedisBloom/RedisBloom.git + description: "Probabilistic data structures: Bloom/Cuckoo filters, Count-Min Sketch, Top-K, t-digest." + tags: [probabilistic] + category: Probabilistic Data Structures - url: https://github.com/RediSearch/RediSearch.git + description: "Secondary index, full-text search, vector search, and aggregation query engine." + tags: [search] + category: Search & Indexing - url: https://github.com/swilly22/redis-graph.git + description: "Early graph database module for Redis (development moved to RedisGraph main repo)." + tags: [graph] + category: Infrastructure & Utilities - url: https://github.com/RedisTimeSeries/RedisTimeSeries.git + description: "Time-series data type with downsampling, compaction, and aggregation queries." + tags: [timeseries] + category: Infrastructure & Utilities - url: https://github.com/danni-m/redis-timeseries.git + description: "Early Redis time-series implementation (superseded by RedisTimeSeries)." + tags: [timeseries] + category: Infrastructure & Utilities - url: https://github.com/sewenew/redis-protobuf.git + description: "Protobuf messages as a native Redis type with field-level path access." + tags: [datatype] + category: Data Types - url: https://github.com/ekzhang/redis-rope.git + description: "High-performance Rope (large string) data type backed by a Splay Tree." + tags: [datatype] + category: Data Types - url: https://github.com/OhBonsai/RedisTree.git + description: "Polytree (multi-way tree) native data type for hierarchical / organizational data." + tags: [datatype] + category: Data Types - url: https://github.com/zhao-lang/redis_hnsw.git + description: "Approximate nearest-neighbor vector search using the HNSW algorithm." + tags: [search] + category: Search & Indexing - url: https://github.com/RedisJSON/RedisJSON2.git + description: "JSON as a native Redis data type with JSONPath operations (superseded by RedisJSON)." + tags: [datatype] + category: Data Types - url: https://github.com/wujunwei/redlock.git + description: "Distributed lock implementation as a Redis module." + tags: [utility] + category: Infrastructure & Utilities - url: https://github.com/sewenew/redis-llm.git + description: "LLM, prompt, vector store, and conversational / retrieval application integration." + tags: [ai] + category: AI & Programmability - url: https://github.com/limithit/RedisPushIptables.git + description: "Redis-driven iptables push / linkage security firewall module." + tags: [utility] + category: Infrastructure & Utilities - url: https://github.com/RedisLabsModules/secondary.git + description: "Early secondary index module with SQL-like hash-field queries (superseded by RediSearch)." + tags: [search] + category: Search & Indexing - url: https://github.com/starkdg/reventis.git + description: "Spatio-temporal event indexing, range queries, and object tracking via space-filling curves." + tags: [timeseries] + category: Infrastructure & Utilities - url: https://github.com/linfangrong/redismodule-ratelimit.git + description: "Token-bucket rate limiter implemented as a Redis module." + tags: [ratelimit] + category: Infrastructure & Utilities - url: https://github.com/starkdg/Redis-ImageScout.git + description: "Perceptual-hash (pHash) image similarity search using MVP-trees." + tags: [search] + category: Search & Indexing - url: https://github.com/danitseitlin/redis-interval-sets.git + description: "Interval-set data type for storing and querying numeric ranges." + tags: [datatype] + category: Data Types - url: https://github.com/poga/redis-percentile.git + description: "Approximate percentile (quantile) statistics module." + tags: [probabilistic] + category: Probabilistic Data Structures - url: https://github.com/gsquire/redis-multi-map.git + description: "Multi-value map (multi-map) data type written in Rust." + tags: [datatype] + category: Data Types - url: https://github.com/ayarotsky/redis-shield.git + description: "Token-bucket rate limiter with native Valkey/Redis commands, written in Rust." + tags: [ratelimit] + category: Infrastructure & Utilities - url: https://github.com/infobip/redis-fpn.git + description: "Fixed-point-number data type with arithmetic commands for Redis 4." + tags: [datatype] + category: Data Types - url: https://github.com/itamarhaber/zpop.git + description: "ZPOP (pop min/max from sorted set) command extension." + tags: [utility] + category: Infrastructure & Utilities - url: https://github.com/halaei/lqrm.git + description: "Laravel-compatible queue driver with server-side millisecond timing and reliable blocking pop." + tags: [utility] + category: Infrastructure & Utilities - url: https://github.com/tair-opensource/TairHash.git + description: "Enhanced Hash with field-level TTL, versioning, and active expiry notifications." + tags: [tair] + category: Data Types - url: https://github.com/tair-opensource/TairString.git + description: "Enhanced String with CAS/CAD, versioning, flags, and memcached protocol support." + tags: [tair] + category: Data Types - url: https://github.com/tair-opensource/TairZset.git + description: "Enhanced ZSet supporting multi-dimensional (up to 255) score sorting." + tags: [tair] + category: Data Types - url: https://github.com/tair-opensource/TairGis.git + description: "R-Tree-based geospatial module with point/line/polygon intersect, contain, and within queries." + tags: [tair, geo] + category: Data Types - url: https://github.com/RedisLabs/redisraft.git + description: "Strongly-consistent Redis cluster built on the Raft consensus algorithm." + tags: [consensus] + category: Infrastructure & Utilities - url: https://github.com/RedisLabsModules/redex.git + description: "Command-extension collection for Keys, Strings, Hashes, Lists, Sets, ZSets, and Geo." + tags: [utility] + category: Infrastructure & Utilities - url: https://github.com/RedisLabsModules/RedisX.git + description: "Native data-type and command extensions (e.g. X.GETSETEX)." + tags: [utility] + category: Infrastructure & Utilities - url: https://github.com/RedisLabsModules/topk.git + description: "Top-K heavy-hitter data structure (superseded by RedisBloom)." + tags: [probabilistic] + category: Probabilistic Data Structures - url: https://github.com/RedisLabsModules/countminsketch.git + description: "Early Count-Min Sketch approximate counting module (superseded by RedisBloom)." + tags: [probabilistic] + category: Probabilistic Data Structures - url: https://github.com/RedisLabsModules/pam_auth.git + description: "Proof-of-concept replacing Redis native AUTH with Linux PAM authentication." + tags: [auth] + category: Infrastructure & Utilities - url: https://github.com/RedisLabsModules/password.git + description: "Secure password-hash storage and verification using bcrypt." + tags: [auth] + category: Infrastructure & Utilities - url: https://github.com/RedisLabsModules/rtexp.git + description: "Fine-grained element expiry management for real-time applications." + tags: [utility] + category: Infrastructure & Utilities - url: https://github.com/RedisLabsModules/graphicsmagick.git + description: "Proof-of-concept in-Redis image processing (rotate, etc.) via GraphicsMagick." + tags: [utility] + category: Infrastructure & Utilities - url: https://github.com/valkey-io/valkey-bloom.git + description: "Probabilistic data structures (Bloom/Cuckoo filters, Count-Min Sketch, Top-K) for Valkey." + tags: [probabilistic] + category: Probabilistic Data Structures - url: https://github.com/valkey-io/valkey-json.git + description: "Native JSON data type with JSONPath operations for Valkey." + tags: [datatype] + category: Data Types - url: https://github.com/valkey-io/valkey-search.git + description: "Full-text search, vector search, and secondary indexing for Valkey." + tags: [search] + category: Search & Indexing - url: https://github.com/valkey-io/valkey-ldap.git + description: "LDAP authentication integration for Valkey." + tags: [auth] + category: Infrastructure & Utilities - url: https://github.com/valkey-io/valkey-luajit.git + description: "LuaJIT scripting engine for Valkey with enhanced performance." + tags: [programmable] + category: AI & Programmability - url: https://github.com/goodform/valkey-datasketches.git + description: "Apache DataSketches integration providing quantile, frequency, and cardinality sketches for Valkey." + tags: [probabilistic] + category: Probabilistic Data Structures - url: https://github.com/chayim/redicrypt.git + description: "Encryption-at-rest module for Redis/Valkey data." + tags: [auth] + category: Infrastructure & Utilities diff --git a/readme.md b/readme.md index 32fd489..149c745 100644 --- a/readme.md +++ b/readme.md @@ -7,6 +7,11 @@ This project is developed and maintained by the [Resources team][team]. ## Contents - [Libraries](#libraries) + - [Infrastructure & Utilities](#infrastructure--utilities) + - [Data Types](#data-types) + - [Probabilistic Data Structures](#probabilistic-data-structures) + - [AI & Programmability](#ai--programmability) + - [Search & Indexing](#search--indexing) - [SDKs](#sdks) - [Tools](#tools) - [Resources](#resources) @@ -14,63 +19,100 @@ This project is developed and maintained by the [Resources team][team]. ## Libraries -| Repo | License | Last Commit Time | -| ----------------------------------------------------------------------------------------- | ---------------------------------- | ------------------- | -| [RediSearch/RediSearch](https://github.com/RediSearch/RediSearch) | Redis Source Available License 2.0 | 2026-06-12 20:29:27 | -| [RedisTimeSeries/RedisTimeSeries](https://github.com/RedisTimeSeries/RedisTimeSeries) | Redis Source Available License 2.0 | 2026-06-11 22:04:27 | -| [valkey-io/valkey-search](https://github.com/valkey-io/valkey-search) | BSD 3-Clause License | 2026-06-11 16:42:28 | -| [valkey-io/valkey-json](https://github.com/valkey-io/valkey-json) | BSD 3-Clause License | 2026-06-11 11:53:07 | -| [goodform/valkey-datasketches](https://github.com/goodform/valkey-datasketches) | BSD 3-Clause License | 2026-06-11 00:26:38 | -| [RedisBloom/RedisBloom](https://github.com/RedisBloom/RedisBloom) | Redis Source Available License 2.0 | 2026-06-10 15:41:34 | -| [valkey-io/valkey-bloom](https://github.com/valkey-io/valkey-bloom) | BSD 3-Clause License | 2026-06-10 13:28:39 | -| [valkey-io/valkey-luajit](https://github.com/valkey-io/valkey-luajit) | BSD 3-Clause License | 2026-06-03 11:34:55 | -| [ayarotsky/redis-shield](https://github.com/ayarotsky/redis-shield) | MIT License | 2026-06-02 10:17:33 | -| [valkey-io/valkey-ldap](https://github.com/valkey-io/valkey-ldap) | BSD 3-Clause License | 2026-05-21 15:10:18 | -| [aviggiano/redis-roaring](https://github.com/aviggiano/redis-roaring) | MIT License | 2026-05-08 02:45:23 | -| [sewenew/redis-llm](https://github.com/sewenew/redis-llm) | Apache License | 2026-05-02 07:07:18 | -| [brandur/redis-cell](https://github.com/brandur/redis-cell) | MIT License | 2026-02-14 10:31:37 | -| [tair-opensource/TairHash](https://github.com/tair-opensource/TairHash) | Apache License | 2026-01-26 14:44:38 | -| [RedisGears/RedisGears](https://github.com/RedisGears/RedisGears) | Redis Source Available License 2.0 | 2025-08-28 18:16:50 | -| [RedisAI/RedisAI](https://github.com/RedisAI/RedisAI) | Redis Source Available License 2.0 | 2025-08-20 09:34:36 | -| [tair-opensource/TairGis](https://github.com/tair-opensource/TairGis) | Apache License | 2025-06-05 14:50:39 | -| [tair-opensource/TairString](https://github.com/tair-opensource/TairString) | Apache License | 2024-11-13 10:31:39 | -| [tzongw/redis-timer](https://github.com/tzongw/redis-timer) | MIT License | 2024-05-03 15:26:22 | -| [chayim/redicrypt](https://github.com/chayim/redicrypt) | Unknown license | 2023-10-10 15:21:54 | -| [RedisLabs/redisraft](https://github.com/RedisLabs/redisraft) | Redis Source Available License 2.0 | 2023-07-18 15:19:06 | -| [wujunwei/redlock](https://github.com/wujunwei/redlock) | MIT License | 2023-02-19 20:51:24 | -| [tair-opensource/TairZset](https://github.com/tair-opensource/TairZset) | Apache License | 2022-12-06 21:49:47 | -| [ekzhang/redis-rope](https://github.com/ekzhang/redis-rope) | MIT License | 2022-09-05 00:02:39 | -| [danitseitlin/redis-interval-sets](https://github.com/danitseitlin/redis-interval-sets) | BSD 3-Clause License | 2022-06-17 11:21:10 | -| [sewenew/redis-protobuf](https://github.com/sewenew/redis-protobuf) | Apache License | 2022-06-13 21:55:48 | -| [halaei/lqrm](https://github.com/halaei/lqrm) | BSD 3-Clause License | 2022-01-18 19:56:38 | -| [starkdg/reventis](https://github.com/starkdg/reventis) | Redis Source Available License | 2021-10-31 15:41:10 | -| [OhBonsai/RedisTree](https://github.com/OhBonsai/RedisTree) | MIT License | 2021-07-07 10:00:51 | -| [usmanm/redis-tdigest](https://github.com/usmanm/redis-tdigest) | MIT License | 2021-01-14 15:14:41 | -| [RedisLabsModules/secondary](https://github.com/RedisLabsModules/secondary) | GNU GPL | 2020-10-19 17:55:29 | -| [starkdg/Redis-ImageScout](https://github.com/starkdg/Redis-ImageScout) | Redis Source Available License | 2020-10-01 22:13:18 | -| [zhao-lang/redis_hnsw](https://github.com/zhao-lang/redis_hnsw) | MIT License | 2020-09-01 19:57:26 | -| [linfangrong/redismodule-ratelimit](https://github.com/linfangrong/redismodule-ratelimit) | MIT License | 2020-04-21 11:24:13 | -| [RedisJSON/RedisJSON2](https://github.com/RedisJSON/RedisJSON2) | Redis Source Available License | 2020-04-20 19:40:37 | -| [TamarLabs/ReDe](https://github.com/TamarLabs/ReDe) | MIT License | 2020-03-03 13:55:26 | -| [swilly22/redis-graph](https://github.com/swilly22/redis-graph) | GNU GPL | 2020-02-13 15:09:43 | -| [poga/redis-percentile](https://github.com/poga/redis-percentile) | MIT License | 2019-12-26 18:00:34 | -| [f0rmiga/sessiongate](https://github.com/f0rmiga/sessiongate) | MIT License | 2019-11-11 15:10:07 | -| [RedisLabsModules/RedisX](https://github.com/RedisLabsModules/RedisX) | Redis Source Available License | 2019-11-01 10:08:36 | -| [RedisLabsModules/redex](https://github.com/RedisLabsModules/redex) | GNU GPL | 2019-07-25 11:32:34 | -| [RedisLabsModules/topk](https://github.com/RedisLabsModules/topk) | GNU GPL | 2019-07-16 15:48:48 | -| [RedisLabsModules/countminsketch](https://github.com/RedisLabsModules/countminsketch) | GNU GPL | 2019-07-16 15:47:33 | -| [sklivvz/cthulhu](https://github.com/sklivvz/cthulhu) | BSD 3-Clause License | 2019-06-28 11:09:41 | -| [limithit/RedisPushIptables](https://github.com/limithit/RedisPushIptables) | GNU GPL | 2019-04-26 08:55:38 | -| [gsquire/redis-multi-map](https://github.com/gsquire/redis-multi-map) | MIT License | 2019-02-20 19:59:22 | -| [RedisLabsModules/rtexp](https://github.com/RedisLabsModules/rtexp) | Apache License | 2018-12-11 15:39:41 | -| [danni-m/redis-timeseries](https://github.com/danni-m/redis-timeseries) | Apache License | 2018-09-28 16:11:31 | -| [infobip/redis-fpn](https://github.com/infobip/redis-fpn) | Apache License | 2018-08-29 14:18:38 | -| [antirez/neural-redis](https://github.com/antirez/neural-redis) | Unknown license | 2018-06-22 12:00:25 | -| [itamarhaber/zpop](https://github.com/itamarhaber/zpop) | Unknown license | 2018-05-17 15:31:00 | -| [erans/redissnowflake](https://github.com/erans/redissnowflake) | Unknown license | 2017-05-11 08:48:57 | -| [RedisLabsModules/password](https://github.com/RedisLabsModules/password) | GNU GPL | 2016-05-18 23:49:12 | -| [RedisLabsModules/graphicsmagick](https://github.com/RedisLabsModules/graphicsmagick) | GNU GPL | 2016-05-08 14:21:21 | -| [RedisLabsModules/pam_auth](https://github.com/RedisLabsModules/pam_auth) | GNU GPL | 2016-05-05 13:51:40 | +### Infrastructure & Utilities + +Rate limiters, authentication modules, consensus protocols, time-series engines, distributed locks, timers, ID generators, and other infrastructure building blocks. + + +| Repo | Description | Tags | Status | +| ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ------------ | ------------------------------------------------- | +| [RedisTimeSeries/RedisTimeSeries](https://github.com/RedisTimeSeries/RedisTimeSeries) | Time-series data type with downsampling, compaction, and aggregation queries. | `timeseries` | 2026-06-11 · Redis Source Available License 2.0 | +| [ayarotsky/redis-shield](https://github.com/ayarotsky/redis-shield) | Token-bucket rate limiter with native Valkey/Redis commands, written in Rust. | `ratelimit` | 2026-06-02 · MIT License | +| [valkey-io/valkey-ldap](https://github.com/valkey-io/valkey-ldap) | LDAP authentication integration for Valkey. | `auth` | 2026-05-21 · BSD 3-Clause License | +| [brandur/redis-cell](https://github.com/brandur/redis-cell) | Single-command rate limiter using the GCRA algorithm. | `ratelimit` | 2026-02-14 · MIT License | +| [tzongw/redis-timer](https://github.com/tzongw/redis-timer) | In-process Lua script scheduler supporting periodic and one-shot timers. | `utility` | *2024-05-03* · MIT License | +| [chayim/redicrypt](https://github.com/chayim/redicrypt) | Encryption-at-rest module for Redis/Valkey data. | `auth` | *2023-10-10* · Unknown license | +| [RedisLabs/redisraft](https://github.com/RedisLabs/redisraft) | Strongly-consistent Redis cluster built on the Raft consensus algorithm. | `consensus` | *2023-07-18* · Redis Source Available License 2.0 | +| [wujunwei/redlock](https://github.com/wujunwei/redlock) | Distributed lock implementation as a Redis module. | `utility` | *2023-02-19* · MIT License | +| [halaei/lqrm](https://github.com/halaei/lqrm) | Laravel-compatible queue driver with server-side millisecond timing and reliable blocking pop. | `utility` | *2022-01-18* · BSD 3-Clause License | +| [starkdg/reventis](https://github.com/starkdg/reventis) | Spatio-temporal event indexing, range queries, and object tracking via space-filling curves. | `timeseries` | *2021-10-31* · Redis Source Available License | +| [linfangrong/redismodule-ratelimit](https://github.com/linfangrong/redismodule-ratelimit) | Token-bucket rate limiter implemented as a Redis module. | `ratelimit` | *2020-04-21* · MIT License | +| [TamarLabs/ReDe](https://github.com/TamarLabs/ReDe) | Lawn-based data dehydrator managing millions of deferred elements with timed replay. | `timeseries` | *2020-03-03* · MIT License | +| [swilly22/redis-graph](https://github.com/swilly22/redis-graph) | Early graph database module for Redis (development moved to RedisGraph main repo). | `graph` | *2020-02-13* · GNU GPL | +| [f0rmiga/sessiongate](https://github.com/f0rmiga/sessiongate) | HTTP session management backed by Redis with pluggable storage backends. | `utility` | *2019-11-11* · MIT License | +| [RedisLabsModules/RedisX](https://github.com/RedisLabsModules/RedisX) | Native data-type and command extensions (e.g. X.GETSETEX). | `utility` | *2019-11-01* · Redis Source Available License | +| [RedisLabsModules/redex](https://github.com/RedisLabsModules/redex) | Command-extension collection for Keys, Strings, Hashes, Lists, Sets, ZSets, and Geo. | `utility` | *2019-07-25* · GNU GPL | +| [limithit/RedisPushIptables](https://github.com/limithit/RedisPushIptables) | Redis-driven iptables push / linkage security firewall module. | `utility` | *2019-04-26* · GNU GPL | +| [RedisLabsModules/rtexp](https://github.com/RedisLabsModules/rtexp) | Fine-grained element expiry management for real-time applications. | `utility` | *2018-12-11* · Apache License | +| [danni-m/redis-timeseries](https://github.com/danni-m/redis-timeseries) | Early Redis time-series implementation (superseded by RedisTimeSeries). | `timeseries` | *2018-09-28* · Apache License | +| [itamarhaber/zpop](https://github.com/itamarhaber/zpop) | ZPOP (pop min/max from sorted set) command extension. | `utility` | *2018-05-17* · Unknown license | +| [erans/redissnowflake](https://github.com/erans/redissnowflake) | Twitter Snowflake-style 64-bit unique time-ordered ID generation. | `id` | *2017-05-11* · Unknown license | +| [RedisLabsModules/password](https://github.com/RedisLabsModules/password) | Secure password-hash storage and verification using bcrypt. | `auth` | *2016-05-18* · GNU GPL | +| [RedisLabsModules/graphicsmagick](https://github.com/RedisLabsModules/graphicsmagick) | Proof-of-concept in-Redis image processing (rotate, etc.) via GraphicsMagick. | `utility` | *2016-05-08* · GNU GPL | +| [RedisLabsModules/pam_auth](https://github.com/RedisLabsModules/pam_auth) | Proof-of-concept replacing Redis native AUTH with Linux PAM authentication. | `auth` | *2016-05-05* · GNU GPL | + +### Data Types + +Modules that extend Valkey/Redis with new native data types, such as JSON, protobuf, Roaring Bitmaps, interval sets, and enhanced Hash/String/ZSet variants. + + +| Repo | Description | Tags | Status | +| --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ------------ | --------------------------------------------- | +| [valkey-io/valkey-json](https://github.com/valkey-io/valkey-json) | Native JSON data type with JSONPath operations for Valkey. | `datatype` | 2026-06-11 · BSD 3-Clause License | +| [aviggiano/redis-roaring](https://github.com/aviggiano/redis-roaring) | Compressed Roaring Bitmap commands powered by CRoaring. | `datatype` | 2026-05-08 · MIT License | +| [tair-opensource/TairHash](https://github.com/tair-opensource/TairHash) | Enhanced Hash with field-level TTL, versioning, and active expiry notifications. | `tair` | 2026-01-26 · Apache License | +| [tair-opensource/TairGis](https://github.com/tair-opensource/TairGis) | R-Tree-based geospatial module with point/line/polygon intersect, contain, and within queries. | `tair` `geo` | 2025-06-05 · Apache License | +| [tair-opensource/TairString](https://github.com/tair-opensource/TairString) | Enhanced String with CAS/CAD, versioning, flags, and memcached protocol support. | `tair` | 2024-11-13 · Apache License | +| [tair-opensource/TairZset](https://github.com/tair-opensource/TairZset) | Enhanced ZSet supporting multi-dimensional (up to 255) score sorting. | `tair` | *2022-12-06* · Apache License | +| [ekzhang/redis-rope](https://github.com/ekzhang/redis-rope) | High-performance Rope (large string) data type backed by a Splay Tree. | `datatype` | *2022-09-05* · MIT License | +| [danitseitlin/redis-interval-sets](https://github.com/danitseitlin/redis-interval-sets) | Interval-set data type for storing and querying numeric ranges. | `datatype` | *2022-06-17* · BSD 3-Clause License | +| [sewenew/redis-protobuf](https://github.com/sewenew/redis-protobuf) | Protobuf messages as a native Redis type with field-level path access. | `datatype` | *2022-06-13* · Apache License | +| [OhBonsai/RedisTree](https://github.com/OhBonsai/RedisTree) | Polytree (multi-way tree) native data type for hierarchical / organizational data. | `datatype` | *2021-07-07* · MIT License | +| [RedisJSON/RedisJSON2](https://github.com/RedisJSON/RedisJSON2) | JSON as a native Redis data type with JSONPath operations (superseded by RedisJSON). | `datatype` | *2020-04-20* · Redis Source Available License | +| [gsquire/redis-multi-map](https://github.com/gsquire/redis-multi-map) | Multi-value map (multi-map) data type written in Rust. | `datatype` | *2019-02-20* · MIT License | +| [infobip/redis-fpn](https://github.com/infobip/redis-fpn) | Fixed-point-number data type with arithmetic commands for Redis 4. | `datatype` | *2018-08-29* · Apache License | + +### Probabilistic Data Structures + +Memory-efficient approximate data structures including Bloom and Cuckoo filters, Count-Min Sketch, Top-K, t-digest, and Apache DataSketches integration. + + +| Repo | Description | Tags | Status | +| ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------- | ----------------------------------------------- | +| [goodform/valkey-datasketches](https://github.com/goodform/valkey-datasketches) | Apache DataSketches integration providing quantile, frequency, and cardinality sketches for Valkey. | `probabilistic` | 2026-06-11 · BSD 3-Clause License | +| [RedisBloom/RedisBloom](https://github.com/RedisBloom/RedisBloom) | Probabilistic data structures: Bloom/Cuckoo filters, Count-Min Sketch, Top-K, t-digest. | `probabilistic` | 2026-06-10 · Redis Source Available License 2.0 | +| [valkey-io/valkey-bloom](https://github.com/valkey-io/valkey-bloom) | Probabilistic data structures (Bloom/Cuckoo filters, Count-Min Sketch, Top-K) for Valkey. | `probabilistic` | 2026-06-10 · BSD 3-Clause License | +| [usmanm/redis-tdigest](https://github.com/usmanm/redis-tdigest) | Online quantile and CDF estimation via merging t-digest sketches. | `probabilistic` | *2021-01-14* · MIT License | +| [poga/redis-percentile](https://github.com/poga/redis-percentile) | Approximate percentile (quantile) statistics module. | `probabilistic` | *2019-12-26* · MIT License | +| [RedisLabsModules/topk](https://github.com/RedisLabsModules/topk) | Top-K heavy-hitter data structure (superseded by RedisBloom). | `probabilistic` | *2019-07-16* · GNU GPL | +| [RedisLabsModules/countminsketch](https://github.com/RedisLabsModules/countminsketch) | Early Count-Min Sketch approximate counting module (superseded by RedisBloom). | `probabilistic` | *2019-07-16* · GNU GPL | + +### AI & Programmability + +In-database machine-learning inference, LLM integration, neural-network data types, and programmable scripting engines that run user-defined logic inside Valkey/Redis. + + +| Repo | Description | Tags | Status | +| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | -------------- | ----------------------------------------------- | +| [valkey-io/valkey-luajit](https://github.com/valkey-io/valkey-luajit) | LuaJIT scripting engine for Valkey with enhanced performance. | `programmable` | 2026-06-03 · BSD 3-Clause License | +| [sewenew/redis-llm](https://github.com/sewenew/redis-llm) | LLM, prompt, vector store, and conversational / retrieval application integration. | `ai` | 2026-05-02 · Apache License | +| [RedisGears/RedisGears](https://github.com/RedisGears/RedisGears) | Programmable execution engine running JavaScript functions and triggers inside Redis. | `programmable` | 2025-08-28 · Redis Source Available License 2.0 | +| [RedisAI/RedisAI](https://github.com/RedisAI/RedisAI) | In-Redis deep-learning / ML model inference workload runner (archived). | `ai` | 2025-08-20 · Redis Source Available License 2.0 | +| [sklivvz/cthulhu](https://github.com/sklivvz/cthulhu) | Embed pre-compiled JavaScript extensions via duktape for custom commands. | `programmable` | *2019-06-28* · BSD 3-Clause License | +| [antirez/neural-redis](https://github.com/antirez/neural-redis) | Feed-forward neural network as a native data type with inline training and inference. | `ai` | *2018-06-22* · Unknown license | + +### Search & Indexing + +Full-text search, vector similarity search, secondary indexing, and image similarity modules that add query capabilities beyond the built-in Valkey/Redis commands. + + +| Repo | Description | Tags | Status | +| --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------- | ----------------------------------------------- | +| [RediSearch/RediSearch](https://github.com/RediSearch/RediSearch) | Secondary index, full-text search, vector search, and aggregation query engine. | `search` | 2026-06-12 · Redis Source Available License 2.0 | +| [valkey-io/valkey-search](https://github.com/valkey-io/valkey-search) | Full-text search, vector search, and secondary indexing for Valkey. | `search` | 2026-06-11 · BSD 3-Clause License | +| [RedisLabsModules/secondary](https://github.com/RedisLabsModules/secondary) | Early secondary index module with SQL-like hash-field queries (superseded by RediSearch). | `search` | *2020-10-19* · GNU GPL | +| [starkdg/Redis-ImageScout](https://github.com/starkdg/Redis-ImageScout) | Perceptual-hash (pHash) image similarity search using MVP-trees. | `search` | *2020-10-01* · Redis Source Available License | +| [zhao-lang/redis_hnsw](https://github.com/zhao-lang/redis_hnsw) | Approximate nearest-neighbor vector search using the HNSW algorithm. | `search` | *2020-09-01* · MIT License | ## SDKs diff --git a/readme.md.tpl b/readme.md.tpl index 0da31db..227eb8f 100644 --- a/readme.md.tpl +++ b/readme.md.tpl @@ -6,7 +6,7 @@ This project is developed and maintained by the [Resources team][team]. ## Contents -- [Libraries](#libraries) +{{LIBRARIES_TOC}} - [SDKs](#sdks) - [Tools](#tools) - [Resources](#resources) diff --git a/scripts/format-awesome-resp.py b/scripts/format-awesome-resp.py index 9e285d1..0b8955d 100644 --- a/scripts/format-awesome-resp.py +++ b/scripts/format-awesome-resp.py @@ -37,8 +37,9 @@ DEFAULT_OUTPUT_FILE = REPO_ROOT / "readme.md" DEFAULT_TMP_DIR = REPO_ROOT / "tmp" -PLACEHOLDER = "{{LIBRARIES_TABLE}}" -TABLE_HEADERS = ("Repo", "License", "Last Commit Time") +PLACEHOLDER_TABLE = "{{LIBRARIES_TABLE}}" +PLACEHOLDER_TOC = "{{LIBRARIES_TOC}}" +TABLE_HEADERS = ("Repo", "Description", "Tags", "Status") # Ordered (specific -> generic) so that "Redis Source Available License 2.0" # is matched before the generic "Redis Source Available License". @@ -58,12 +59,44 @@ # YAML loading # --------------------------------------------------------------------------- -def load_libraries(file_path): - """Read ``libraries.yml`` from disk and return ``[(url, branch_or_none), ...]``. +def load_categories(file_path): + """Read the ``categories`` section from ``libraries.yml``. @param file_path Path to the YAML file. - @return List of (url, branch) tuples preserving file order. - @exit 1 if the file is missing or has no entries. + @return ``(valid_names, descriptions)`` tuple where + ``valid_names`` is a ``set`` of allowed category names + and ``descriptions`` is a ``dict`` mapping name -> text. + @exit 1 if the ``categories`` section is missing or empty. + """ + path = Path(file_path) + data = yaml.safe_load(path.read_text()) + cats = data.get("categories") + if not isinstance(cats, list) or not cats: + print("Invalid libraries.yml: top-level 'categories' must be a non-empty list") + sys.exit(1) + + valid_names = set() + descriptions = {} + for idx, item in enumerate(cats): + name = item.get("name") + if not name: + print(f"Skip categories entry #{idx}: missing 'name'") + continue + valid_names.add(name) + descriptions[name] = item.get("description", "") + if not valid_names: + print("No valid category names found in libraries.yml") + sys.exit(1) + return valid_names, descriptions + + +def load_libraries(file_path, valid_categories): + """Read ``libraries.yml`` from disk and return ``[(url, branch, description, tags, category), ...]``. + + @param file_path Path to the YAML file. + @param valid_categories Set of allowed category names (from ``load_categories``). + @return List of (url, branch, description, tags, category) tuples preserving file order. + @exit 1 if the file is missing or has no entries. """ path = Path(file_path) if not path.is_file(): @@ -71,16 +104,28 @@ def load_libraries(file_path): sys.exit(1) data = yaml.safe_load(path.read_text()) - if not isinstance(data, dict) or not isinstance(data.get("libraries"), list) or not data["libraries"]: + libs = data.get("libraries") + if not isinstance(libs, list) or not libs: print("Invalid libraries.yml: top-level 'libraries' must be a non-empty list") sys.exit(1) out = [] - for idx, item in enumerate(data["libraries"]): + for idx, item in enumerate(libs): if not isinstance(item, dict) or not item.get("url"): print(f"Skip entry #{idx}: missing 'url'") continue - out.append((item["url"], item.get("branch"))) + category = item.get("category", "") + if category not in valid_categories: + print(f"ERROR: entry #{idx} ({item['url']}) has invalid category " + f"'{category}'. Valid categories: {sorted(valid_categories)}") + sys.exit(1) + out.append(( + item["url"], + item.get("branch"), + item.get("description", ""), + item.get("tags", []), + category, + )) return out @@ -88,46 +133,116 @@ def load_libraries(file_path): # Per-repository helpers # --------------------------------------------------------------------------- -def clone_repo(url, branch, dest_root): - """Clone ``url`` into ``dest_root/`` with ``--depth 1``. +def _repo_name_from_url(url): + """Extract the bare repo name from a clone URL.""" + name = os.path.basename(url) + if name.endswith(".git"): + name = name[:-len(".git")] + return name - @param url Git clone URL (typically ending with ``.git``). - @param branch Optional branch name; ``None`` for the remote default. - @param dest_root Directory in which the clone is created. - @return Path to the cloned repository on success, else ``None``. + +def _git_env(): + """Return an environment dict with ``GIT_LFS_SKIP_SMUDGE=1`` set. + + Some repos (e.g. RedisAI) enable LFS, but when the remote disables LFS, + ``git clone`` / ``git fetch`` fails with "smudge filter lfs failed". We + only need the LICENSE files and the last commit time, never the actual LFS + payloads, so skipping the smudge filter is safe. """ - repo_name = os.path.basename(url) - if repo_name.endswith(".git"): - repo_name = repo_name[:-len(".git")] - target = Path(dest_root) / repo_name + env = os.environ.copy() + env["GIT_LFS_SKIP_SMUDGE"] = "1" + return env + +def _do_clone(url, branch, target): + """Perform a fresh ``git clone --depth 1`` into ``target``. + + @return ``target`` on success, ``None`` on failure. + """ cmd = ["git", "clone", "--quiet", "--depth", "1"] if branch: cmd += ["-b", branch, "--single-branch"] cmd += [url, str(target)] - # Skip the Git LFS smudge filter. Some repos (e.g. RedisAI) enable LFS, - # but when the remote disables LFS, ``git clone`` fails with - # "smudge filter lfs failed". We only need the LICENSE files and the last - # commit time, never the actual LFS payloads, so setting - # GIT_LFS_SKIP_SMUDGE=1 lets the lfs filter pass through pointers as-is. - env = os.environ.copy() - env["GIT_LFS_SKIP_SMUDGE"] = "1" - try: - rc = subprocess.call(cmd, env=env) + rc = subprocess.call(cmd, env=_git_env()) except subprocess.CalledProcessError: rc = 1 if rc != 0 or not target.is_dir(): - print(f"Failed to clone {url}") return None return target +def ensure_repo(url, branch, dest_root): + """Ensure ``url`` is available at ``dest_root/``. + + If the repo already exists locally, fetch the latest commit via + ``git fetch --depth 1`` + ``git checkout FETCH_HEAD`` instead of + re-cloning. Falls back to a fresh ``git clone --depth 1`` when the + directory is missing, corrupted, or the remote URL has changed. + + @param url Git clone URL (typically ending with ``.git``). + @param branch Optional branch name; ``None`` for the remote default. + @param dest_root Directory in which the repo resides. + @return Path to the repository on success, else ``None``. + """ + repo_name = _repo_name_from_url(url) + target = Path(dest_root) / repo_name + env = _git_env() + + # --- Fast path: repo already exists, try incremental fetch ---------- + if target.is_dir() and (target / ".git").exists(): + # Verify the remote URL still matches the YAML entry. + try: + current_url = subprocess.check_output( + ["git", "remote", "get-url", "origin"], + cwd=target, env=env, + ).decode().strip() + except subprocess.CalledProcessError: + current_url = "" + if current_url.rstrip("/") != url.rstrip("/"): + print(f" Remote URL changed for {repo_name}, re-cloning ...") + shutil.rmtree(target, ignore_errors=True) + return _do_clone(url, branch, target) + + # Fetch the latest commit (shallow). + fetch_cmd = ["git", "fetch", "--depth", "1", "origin"] + if branch: + fetch_cmd.append(branch) + try: + rc = subprocess.call(fetch_cmd, cwd=target, env=env) + except subprocess.CalledProcessError: + rc = 1 + if rc != 0: + print(f" Fetch failed for {repo_name}, re-cloning ...") + shutil.rmtree(target, ignore_errors=True) + return _do_clone(url, branch, target) + + # Move HEAD to the just-fetched commit. + try: + subprocess.check_call( + ["git", "checkout", "-q", "-f", "FETCH_HEAD"], + cwd=target, env=env, + ) + except subprocess.CalledProcessError: + shutil.rmtree(target, ignore_errors=True) + return _do_clone(url, branch, target) + + return target + + # --- Slow path: directory missing or not a git repo ----------------- + if target.exists(): + shutil.rmtree(target, ignore_errors=True) + result = _do_clone(url, branch, target) + if result is None: + print(f"Failed to clone {url}") + return result + + def detect_license(repo_dir): """Detect the license type by scanning license-like files in ``repo_dir``.""" license_files = [] - for root, _dirs, files in os.walk(repo_dir): + for root, _, files in os.walk(repo_dir): for name in files: if name.startswith(LICENSE_FILE_PREFIXES): license_files.append(os.path.join(root, name)) @@ -167,18 +282,18 @@ def format_repo_link(url): return f"[{owner_repo}]({display_url})" -def collect_repo_row(url, branch, tmp_root): - """Clone a repo and assemble a single Markdown table row. +def collect_repo_row(url, branch, description, tags, category, tmp_root): + """Ensure a repo is available and assemble a single Markdown table row. - @return ``[link, license, last_commit_time]`` or ``None`` on failure. + @return ``[link, description, tags, license, last_commit_time, category]`` or ``None`` on failure. """ - repo_dir = clone_repo(url, branch, tmp_root) + repo_dir = ensure_repo(url, branch, tmp_root) if repo_dir is None: return None last_commit = get_last_commit_time(repo_dir) if not last_commit: return None - return [format_repo_link(url), detect_license(repo_dir), last_commit] + return [format_repo_link(url), description, tags, detect_license(repo_dir), last_commit, category] # --------------------------------------------------------------------------- @@ -186,19 +301,49 @@ def collect_repo_row(url, branch, tmp_root): # --------------------------------------------------------------------------- def _sort_by_commit_desc(row): - return datetime.strptime(row[2], "%Y-%m-%d %H:%M:%S") + return datetime.strptime(row[4], "%Y-%m-%d %H:%M:%S") + + +def _format_tags(tags): + """Convert a list of tag strings to inline-code Markdown. + + @param tags List of tag strings (e.g. ``["search", "vector"]``). + @return Space-separated `` `tag` `` items, or ``-`` if empty. + """ + if not tags: + return "-" + return " ".join(f"`{t}`" for t in tags) + + +def _format_license_time(license_str, commit_time_str): + """Merge license and last-commit-time into one cell. + + If the last commit is more than 2 years ago, the time portion is rendered + in *italics*. + @param license_str License name string. + @param commit_time_str ``YYYY-MM-DD HH:MM:SS`` string. + @return ``"license | time"`` or ``"license | *time*"``. + """ + try: + dt = datetime.strptime(commit_time_str, "%Y-%m-%d %H:%M:%S") + except ValueError: + return f"{commit_time_str} · {license_str}" + # Display only the date portion (YYYY-MM-DD). + date_str = dt.strftime("%Y-%m-%d") + if (datetime.now() - dt).days > 730: + return f"*{date_str}* · {license_str}" + return f"{date_str} · {license_str}" -def render_table(rows): - """Render the Markdown table from ``rows`` (list of 3-cell lists). + +def _render_single_table(rows, headers): + """Render a Markdown table from ``rows`` (list of cell lists). Cells are padded so that pipes are vertically aligned, satisfying the ``remark-lint:table-pipe-alignment`` and ``remark-lint:table-cell-padding`` rules used by ``awesome-lint``. """ - rows_sorted = sorted(rows, key=_sort_by_commit_desc, reverse=True) - str_rows = [[str(c) for c in row] for row in rows_sorted] - headers = list(TABLE_HEADERS) + str_rows = [[str(c) for c in row] for row in rows] widths = [len(h) for h in headers] for row in str_rows: for i, cell in enumerate(row): @@ -214,19 +359,101 @@ def fmt_row(cells): return "\n".join([header_line, separator_line, *body]) -def render_readme(template_text, table_md): - """Replace the ``{{LIBRARIES_TABLE}}`` placeholder in the template.""" - if PLACEHOLDER not in template_text: - print(f"Template is missing the {PLACEHOLDER} placeholder") +def _anchor_from_category(cat): + """Convert a category name to a GitHub-compatible anchor slug.""" + return cat.lower().replace(" & ", "--").replace(" ", "-") + + +def render_toc(categories): + """Render the Libraries sub-section of the Contents from a list of category names. + + @param categories Ordered list of category names (as they appear in the YAML). + @return Markdown lines for the Contents section under ``- [Libraries]``. + """ + lines = ["- [Libraries](#libraries)"] + for cat in categories: + anchor = _anchor_from_category(cat) + lines.append(f" - [{cat}](#{anchor})") + return "\n".join(lines) + + +def render_categorized_tables(rows, category_descriptions): + """Render category-grouped Markdown tables from ``rows``. + + Each row is ``[link, description, tags, license, last_commit_time, category]``. + Rows are grouped by ``category``, sorted within each group by last commit + time descending, and rendered as ``### Category Name`` + a Markdown table. + + @param category_descriptions ``dict`` mapping category name -> description text. + @return ``(markdown_string, ordered_category_names)`` tuple. + """ + # Group rows by category. + groups = {} + for row in rows: + cat = row[5] + groups.setdefault(cat, []).append(row) + + # Preserve the order categories first appear in the YAML. + seen = [] + for row in rows: + cat = row[5] + if cat not in seen: + seen.append(cat) + + display_headers = list(TABLE_HEADERS) + + sections = [] + for cat in seen: + cat_rows = groups[cat] + cat_rows.sort(key=_sort_by_commit_desc, reverse=True) + # Build display rows: [link, description, formatted_tags, license|time] + display_rows = [] + for row in cat_rows: + display_rows.append([ + row[0], # link + row[1], # description + _format_tags(row[2]), # tags + _format_license_time(row[3], row[4]), # license & last commit + ]) + desc = category_descriptions.get(cat, "") + section = f"### {cat}\n\n{desc}\n\n{_render_single_table(display_rows, display_headers)}" + sections.append(section) + + return "\n\n".join(sections), seen + + +def render_readme(template_text, categorized_md, toc_md): + """Replace ``{{LIBRARIES_TABLE}}`` and ``{{LIBRARIES_TOC}}`` placeholders.""" + if PLACEHOLDER_TABLE not in template_text: + print(f"Template is missing the {PLACEHOLDER_TABLE} placeholder") sys.exit(1) - return template_text.replace(PLACEHOLDER, table_md) + if PLACEHOLDER_TOC not in template_text: + print(f"Template is missing the {PLACEHOLDER_TOC} placeholder") + sys.exit(1) + text = template_text.replace(PLACEHOLDER_TABLE, categorized_md) + return text.replace(PLACEHOLDER_TOC, toc_md) def _prepare_tmp_dir(tmp_dir): - shutil.rmtree(tmp_dir, ignore_errors=True) + """Ensure the tmp directory exists (no longer clears it on every run).""" os.makedirs(tmp_dir, exist_ok=True) +def _cleanup_stale_repos(tmp_dir, expected_names): + """Remove repo directories in ``tmp_dir`` that are no longer listed in ``libraries.yml``. + + @param tmp_dir Path to the tmp directory. + @param expected_names Set of repo directory names that should be kept. + """ + if not os.path.isdir(tmp_dir): + return + for entry in os.listdir(tmp_dir): + entry_path = os.path.join(tmp_dir, entry) + if os.path.isdir(entry_path) and entry not in expected_names: + print(f" Cleaning up stale repo: {entry}") + shutil.rmtree(entry_path, ignore_errors=True) + + # --------------------------------------------------------------------------- # Pipeline stages # --------------------------------------------------------------------------- @@ -242,7 +469,14 @@ def step_format(args): sys.exit(1) template_text = template_path.read_text() - entries = load_libraries(args.file) + valid_categories, category_descriptions = load_categories(args.file) + entries = load_libraries(args.file, valid_categories) + + # Build the set of expected repo names for stale cleanup *before* dry-run + # truncation so that we never accidentally delete repos that are still + # listed in libraries.yml. + expected_names = {_repo_name_from_url(url) for url, _, _, _, _ in entries} + if args.dry_run: first = entries[0] print(f"[dry-run] cloning only the first entry: {first[0]} (branch={first[1] or 'default'})") @@ -255,23 +489,27 @@ def step_format(args): rows = [] succeeded = 0 failed = 0 - print(f"==> Cloning and inspecting {total} repositor{'y' if total == 1 else 'ies'}...") - for idx, (url, branch) in enumerate(entries, start=1): + print(f"==> Ensuring {total} repositor{'y' if total == 1 else 'ies'} (incremental fetch + fallback clone)...") + for idx, (url, branch, description, tags, category) in enumerate(entries, start=1): prefix = f"[{idx}/{total}]" branch_hint = f" (branch={branch})" if branch else "" print(f"{prefix} {url}{branch_hint}", flush=True) - row = collect_repo_row(url, branch, tmp_dir) + row = collect_repo_row(url, branch, description, tags, category, tmp_dir) if row is not None: rows.append(row) succeeded += 1 - print(f"{prefix} -> ok | {row[1]} | {row[2]}", flush=True) + print(f"{prefix} -> ok | {row[3]} | {row[4]}", flush=True) else: failed += 1 print(f"{prefix} -> FAILED", flush=True) print(f"==> Done: {succeeded} ok, {failed} failed, {total} total") - table_md = render_table(rows) - readme_text = render_readme(template_text, table_md) + # Remove repos that are no longer in libraries.yml. + _cleanup_stale_repos(tmp_dir, expected_names) + + categorized_md, categories = render_categorized_tables(rows, category_descriptions) + toc_md = render_toc(categories) + readme_text = render_readme(template_text, categorized_md, toc_md) if args.stdout: print(readme_text)