From e45fa305226e8c8730e18020967993e6fc2967fe Mon Sep 17 00:00:00 2001 From: Maximilian Date: Fri, 24 Apr 2026 15:36:17 +0200 Subject: [PATCH 1/4] =?UTF-8?q?docs:=20add=20design=20for=20redis=206.2.0?= =?UTF-8?q?=20=E2=86=92=206.3.0=20bump=20(issue=20#38)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2026-04-24-redis-6.3.0-bump-design.md | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-24-redis-6.3.0-bump-design.md diff --git a/docs/superpowers/specs/2026-04-24-redis-6.3.0-bump-design.md b/docs/superpowers/specs/2026-04-24-redis-6.3.0-bump-design.md new file mode 100644 index 0000000..493a7c1 --- /dev/null +++ b/docs/superpowers/specs/2026-04-24-redis-6.3.0-bump-design.md @@ -0,0 +1,135 @@ +# redis PECL 6.2.0 → 6.3.0 bump (PHP 8.5 restoration) + +**Issue:** [#38](https://github.com/buildrush/setup-php/issues/38) +**Status:** Design approved 2026-04-24 +**Depends on:** PR #37 (Phase-2 version expansion) — merged + +## 1. Goal & scope + +Restore redis on PHP 8.5 by bumping the catalog pin from `6.2.0` to `6.3.0`. 6.3.0 is the upstream release that drops the reference to `ext/standard/php_smart_string.h`, an internal PHP header removed in PHP 8.5. redis 6.2.0 still includes that header and fails to compile against 8.5 with: + +``` +/tmp/ext-src/common.h:14:10: fatal error: ext/standard/php_smart_string.h: No such file or directory +``` + +This is a single-purpose slice per the version-expansion spec (`docs/superpowers/specs/2026-04-21-phase2-version-expansion-design.md` §2 non-goals): "Bumping PECL extension versions ... is its own single-purpose slice." + +### In scope + +- Catalog pin bump and removal of the `exclude: [{ php: "8.5" }]` block in `catalog/extensions/redis.yaml`. +- Compat-harness fixture cleanup: revert the apcu substitutions in three 8.5 input-shape fixtures back to redis, and restore redis to the top14 8.5 jumbo fixture. +- `bundles.lock` refresh: PR self-publish CI rebuilds all 10 redis bundles (5 PHP ABIs × 2 arches) and commits the lockfile back to the PR head. + +### Out of scope + +- igbinary 3.2.16 → 3.2.17 bump (tracked in issue #43 — blocked on a stable igbinary release; only 3.2.17RC1 exists at time of writing). +- Any other PECL extension version bumps. +- Runtime Go code changes, builder script changes, workflow YAML changes. +- Backfilling historical design docs or the product-vision example text that still reference `redis 6.2.0`. + +## 2. Changes + +### 2.1 `catalog/extensions/redis.yaml` + +- Change `versions: ["6.2.0"]` to `versions: ["6.3.0"]`. +- Remove the `exclude:` block and its explanatory comment: + +```yaml +exclude: + # redis 6.2.0 references ext/standard/php_smart_string.h which was removed + # in PHP 8.5; compilation fails. Upstream redis 6.3.0 ships the fix, but a + # version bump is its own single-purpose slice per the version-expansion + # spec non-goals. Until that slice lands, redis is unavailable on 8.5. + - { php: "8.5" } +``` + +After the change, the file's `abi_matrix.php` stays `["8.1", "8.2", "8.3", "8.4", "8.5"]` and there are no excludes — redis 6.3.0 is expected to compile cleanly across all supported PHP ABIs. + +### 2.2 `test/compat/fixtures.yaml` + +Three fixtures in the 8.5 input-shape block were substituted from redis to apcu in PR #37 as a temporary workaround. Revert them, and drop the accompanying comment. + +- `multi-ext-85`: `extensions: 'apcu, xdebug'` → `'redis, xdebug'` +- `none-reset-85`: `extensions: 'none, apcu'` → `'none, redis'` +- `single-ext-85`: `extensions: 'apcu'` → `'redis'` +- Remove the 3-line "# redis is excluded on 8.5 (see catalog/extensions/redis.yaml) ..." comment that introduces that fixture block. + +The `multi-ext-top14-arm64-85` fixture (line ~422) currently omits `redis` from its extension list. Restore it: + +- Prepend `redis, ` to its `extensions:` field. +- Replace the preceding "# 8.5 omits redis + igbinary (php_smart_string.h upstream issue; see #38, #43)." comment with "# 8.5 omits igbinary (php_smart_string.h upstream issue; see #43)." + +Rationale for reverting to redis rather than keeping apcu + adding new redis-85 fixtures: + +- PR #37's comment explicitly framed the apcu swap as a substitution ("substitute apcu to cover the same input-shape axes"), not a permanent coverage expansion. +- apcu retains coverage on PHP 8.5 via the top14 jumbo fixture (which lists apcu). +- Keeping apcu would add three new redis-85 fixtures instead of reverting three, growing CI cost without net coverage gain. + +### 2.3 `bundles.lock` + +The spec_hash for every `ext:redis:*` entry changes when the pinned version changes. The PR self-publish flow (same as PR #37) handles this: + +1. Planner detects 10 redis cells with drifted spec_hashes. +2. `build-extension.yml` builds redis 6.3.0 for each cell and pushes the bundle to GHCR. +3. `lockfile-update` job commits the 10 refreshed `bundles.lock` entries back to the PR head. +4. Compat harness then runs against the freshly published bundles. + +Existing lockfile shape: `ext:redis:6.2.0:{8.1,8.2,8.3,8.4}:linux:{x86_64,aarch64}:nts` (8 entries, no 8.5). +After the slice: `ext:redis:6.3.0:{8.1,8.2,8.3,8.4,8.5}:linux:{x86_64,aarch64}:nts` (10 entries). + +### 2.4 Files deliberately not touched + +- `catalog/extensions/igbinary.yaml` — comment says "same class of upstream incompatibility as redis 6.2.0"; that is still accurate historical framing, and #43 is the slice that will revise it. +- `docs/product-vision.md` — example snippets mention `redis:6.2.0`; vision doc is illustrative, not authoritative, and churn here has no functional impact. +- `docs/superpowers/specs/*.md` — frozen-in-time design docs. Do not backfill. + +## 3. Verification + +Per project CLAUDE.md "CI failures: reproduce locally first" rule — we do not iterate by push-and-observe. + +### 3.1 Pre-push local checks + +1. `make check` — Go/JS lint, unit tests, formatting (seconds to minutes). +2. `make ci-cell OS=jammy ARCH=x86_64 PHP=8.5` — the riskiest cell (net-new build); ~20 min. Confirms redis 6.3.0 compiles against PHP 8.5 and the fixtures pass inside bare-ubuntu docker. +3. Optionally `make ci-cell OS=jammy ARCH=x86_64 PHP=8.1` — regression check for the oldest supported PHP, since 6.3.0 could in principle drop older-version support. PECL `package.xml` declares `7.4.0`, so this is a low-probability check; if 8.5 passes locally, defer the remaining 8 cells to PR CI. + +### 3.2 PR CI expectations + +- Planner emits 10 redis rebuild cells. No other extensions share spec_hash inputs with redis, so no ripple. +- `build-extension.yml` succeeds for all 10 cells; bundles pushed to GHCR. +- `lockfile-update` commits refreshed `bundles.lock` to the PR head. +- Compat harness green for every fixture containing redis: + - 8.1–8.4 input-shape fixtures (`multi-ext`, `none-reset`, `single-ext`) — no change, but rebuilt under new spec_hash. + - 8.5 input-shape fixtures (`multi-ext-85`, `none-reset-85`, `single-ext-85`) — newly redis-bearing. + - Top14 multi-ext variants (x86_64 and arm64, all versions including -85). + - Jumbo fixtures containing redis. + +### 3.3 Release-notes review + +Skim the redis PECL 6.2.0 → 6.3.0 changelog (upstream GitHub release notes) for: + +- BC breaks or removed APIs. +- Default-value changes. +- Deprecations users should know about. + +Surface any notable items in the PR body so consumers upgrading the action see them. + +## 4. Risk & rollback + +### 4.1 Risks + +- **6.3.0 introduces a behavior change that breaks consumer code.** Mitigation: minor version bump per semver intent; changelog reviewed upstream; compat harness exercises the existing redis-bearing fixtures. +- **6.3.0 fails to build against an older PHP ABI (8.1–8.4).** Mitigation: PECL metadata shows `7.4.0`; all supported ABIs are above that floor. Local `make ci-cell` covers the riskiest cell pre-push. +- **Spec_hash ripple forces large rebuild.** Expected: 10 redis cells rebuild. Not a regression — it's the intended outcome of a version bump. + +### 4.2 Rollback + +Revert the PR. Old `ext:redis:6.2.0:*` bundles remain content-addressed on GHCR; lockfile entries revert with the PR revert. PHP 8.5 loses redis again (pre-slice state). + +## 5. Success criteria + +- `catalog/extensions/redis.yaml` pins version `6.3.0` with no `exclude:` block. +- `bundles.lock` contains `ext:redis:6.3.0:*` entries for all 10 (ABI × arch) combinations and no `ext:redis:6.2.0:*` entries. +- Compat harness passes with redis present in every fixture that had it pre-PR-#37, plus redis restored in all 8.5 redis-bearing fixtures. +- `make check` and PR CI are green. +- PR body calls out any notable 6.2.0 → 6.3.0 upstream behavior changes for consumers. From 41fbba5c5602148b3e7ed0f18d3baefd2020e36f Mon Sep 17 00:00:00 2001 From: Maximilian Date: Fri, 24 Apr 2026 15:45:06 +0200 Subject: [PATCH 2/4] =?UTF-8?q?feat(catalog):=20bump=20redis=20PECL=206.2.?= =?UTF-8?q?0=20=E2=86=92=206.3.0=20(restores=20PHP=208.5=20support)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- catalog/extensions/redis.yaml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/catalog/extensions/redis.yaml b/catalog/extensions/redis.yaml index 53e4814..b9d6773 100644 --- a/catalog/extensions/redis.yaml +++ b/catalog/extensions/redis.yaml @@ -3,18 +3,12 @@ kind: pecl source: pecl_package: redis versions: - - "6.2.0" + - "6.3.0" abi_matrix: php: ["8.1", "8.2", "8.3", "8.4", "8.5"] os: ["linux"] arch: ["x86_64", "aarch64"] ts: ["nts"] -exclude: - # redis 6.2.0 references ext/standard/php_smart_string.h which was removed - # in PHP 8.5; compilation fails. Upstream redis 6.3.0 ships the fix, but a - # version bump is its own single-purpose slice per the version-expansion - # spec non-goals. Until that slice lands, redis is unavailable on 8.5. - - { php: "8.5" } runtime_deps: linux: [] ini: From 3577717c19a527461a5e8d7aabaef58be1e934eb Mon Sep 17 00:00:00 2001 From: Maximilian Date: Fri, 24 Apr 2026 15:47:06 +0200 Subject: [PATCH 3/4] test(compat): restore redis in PHP 8.5 fixtures after 6.3.0 bump --- test/compat/fixtures.yaml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/test/compat/fixtures.yaml b/test/compat/fixtures.yaml index 1300c55..2dba903 100644 --- a/test/compat/fixtures.yaml +++ b/test/compat/fixtures.yaml @@ -85,24 +85,21 @@ fixtures: coverage: 'none' ini-file: 'development' - # redis is excluded on 8.5 (see catalog/extensions/redis.yaml); these three - # fixtures substitute apcu to cover the same input-shape axes (multi-ext, - # none-reset, single-ext) against an extension that does build on 8.5. - name: multi-ext-85 php-version: '8.5' - extensions: 'apcu, xdebug' + extensions: 'redis, xdebug' ini-values: '' coverage: 'none' - name: none-reset-85 php-version: '8.5' - extensions: 'none, apcu' + extensions: 'none, redis' ini-values: '' coverage: 'none' - name: single-ext-85 php-version: '8.5' - extensions: 'apcu' + extensions: 'redis' ini-values: '' coverage: 'none' @@ -416,11 +413,11 @@ fixtures: ini-values: '' coverage: 'none' - # 8.5 omits redis + igbinary (php_smart_string.h upstream issue; see #38, #43). + # 8.5 omits igbinary (php_smart_string.h upstream issue; see #43). - name: multi-ext-top14-arm64-85 php-version: '8.5' arch: 'aarch64' - extensions: 'xdebug, pcov, apcu, msgpack, uuid, ssh2, yaml, memcached, amqp, event, rdkafka, protobuf' + extensions: 'redis, xdebug, pcov, apcu, msgpack, uuid, ssh2, yaml, memcached, amqp, event, rdkafka, protobuf' ini-values: '' coverage: 'none' From 566739ec1ad9a0109a781256352d9ef19bfeda51 Mon Sep 17 00:00:00 2001 From: Maximilian Date: Fri, 24 Apr 2026 17:00:06 +0200 Subject: [PATCH 4/4] fix(phpup): sync runtime redis version with catalog YAML (6.3.0) The runtime 'phpup install' path used a hardcoded inline catalog in cmd/phpup/main.go that duplicated catalog/extensions/*.yaml version pins. Bumping redis to 6.3.0 in the YAML without updating the inline copy caused resolve failures on PHP 8.5 with 'extension redis 6.2.0 ... not found in lockfile'. Extract the inline extension specs into runtimeExtensionSpecs() and add TestRuntimeExtensionSpecsMatchYAML to catch version/kind drift between the two sources of truth, mirroring the existing TestCatalogBundledMatchesCompat pattern for catalog/php.yaml <-> internal/compat. --- cmd/phpup/main.go | 21 +---------- cmd/phpup/runtime_catalog.go | 30 +++++++++++++++ cmd/phpup/runtime_catalog_test.go | 61 +++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 20 deletions(-) create mode 100644 cmd/phpup/runtime_catalog.go create mode 100644 cmd/phpup/runtime_catalog_test.go diff --git a/cmd/phpup/main.go b/cmd/phpup/main.go index 622b110..5662ecb 100644 --- a/cmd/phpup/main.go +++ b/cmd/phpup/main.go @@ -217,26 +217,7 @@ func main() { p.PHPVersion: {BundledExtensions: bundled}, }, }, - Extensions: map[string]*catalog.ExtensionSpec{ - "redis": {Name: "redis", Kind: catalog.ExtensionKindPECL, Versions: []string{"6.2.0"}}, - "xdebug": {Name: "xdebug", Kind: catalog.ExtensionKindPECL, Versions: []string{"3.5.1"}, Ini: []string{"zend_extension=xdebug"}}, - "pcov": {Name: "pcov", Kind: catalog.ExtensionKindPECL, Versions: []string{"1.0.12"}, Ini: []string{"extension=pcov"}}, - "apcu": {Name: "apcu", Kind: catalog.ExtensionKindPECL, Versions: []string{"5.1.28"}}, - "igbinary": {Name: "igbinary", Kind: catalog.ExtensionKindPECL, Versions: []string{"3.2.16"}}, - "msgpack": {Name: "msgpack", Kind: catalog.ExtensionKindPECL, Versions: []string{"3.0.0"}}, - "uuid": {Name: "uuid", Kind: catalog.ExtensionKindPECL, Versions: []string{"1.3.0"}, RuntimeDeps: map[string][]string{"linux": {"libuuid1"}}}, - "ssh2": {Name: "ssh2", Kind: catalog.ExtensionKindPECL, Versions: []string{"1.5.0"}, RuntimeDeps: map[string][]string{"linux": {"libssh2-1"}}}, - "yaml": {Name: "yaml", Kind: catalog.ExtensionKindPECL, Versions: []string{"2.3.0"}, RuntimeDeps: map[string][]string{"linux": {"libyaml-0-2"}}}, - "memcached": {Name: "memcached", Kind: catalog.ExtensionKindPECL, Versions: []string{"3.4.0"}, RuntimeDeps: map[string][]string{"linux": {"libmemcached11", "libsasl2-2"}}}, - "amqp": {Name: "amqp", Kind: catalog.ExtensionKindPECL, Versions: []string{"2.2.0"}, RuntimeDeps: map[string][]string{"linux": {"librabbitmq4"}}}, - "event": {Name: "event", Kind: catalog.ExtensionKindPECL, Versions: []string{"3.1.4"}, RuntimeDeps: map[string][]string{"linux": {"libevent-2.1-7", "libevent-extra-2.1-7", "libevent-openssl-2.1-7"}}}, - "rdkafka": {Name: "rdkafka", Kind: catalog.ExtensionKindPECL, Versions: []string{"6.0.5"}, RuntimeDeps: map[string][]string{"linux": {"librdkafka1"}}}, - "protobuf": {Name: "protobuf", Kind: catalog.ExtensionKindPECL, Versions: []string{"5.34.1"}}, - "imagick": {Name: "imagick", Kind: catalog.ExtensionKindPECL, Versions: []string{"3.8.1"}, RuntimeDeps: map[string][]string{"linux": {"libfontconfig1", "libx11-6", "libxext6", "liblcms2-2", "liblqr-1-0", "libfftw3-double3", "libbz2-1.0"}}}, - "mongodb": {Name: "mongodb", Kind: catalog.ExtensionKindPECL, Versions: []string{"2.2.1"}, RuntimeDeps: map[string][]string{"linux": {"libssl3", "libsasl2-2"}}}, - "swoole": {Name: "swoole", Kind: catalog.ExtensionKindPECL, Versions: []string{"6.2.0"}, RuntimeDeps: map[string][]string{"linux": {"libssl3", "libcurl4"}}}, - "grpc": {Name: "grpc", Kind: catalog.ExtensionKindPECL, Versions: []string{"1.80.0"}, RuntimeDeps: map[string][]string{"linux": {"libssl3"}}}, - }, + Extensions: runtimeExtensionSpecs(), } // 4. Resolve plan against lockfile diff --git a/cmd/phpup/runtime_catalog.go b/cmd/phpup/runtime_catalog.go new file mode 100644 index 0000000..0025f3b --- /dev/null +++ b/cmd/phpup/runtime_catalog.go @@ -0,0 +1,30 @@ +package main + +import "github.com/buildrush/setup-php/internal/catalog" + +// runtimeExtensionSpecs returns the extension specs used by `phpup install` +// at runtime. These MUST stay in sync with catalog/extensions/*.yaml — see +// TestRuntimeExtensionSpecsMatchYAML in runtime_catalog_test.go for the +// drift guard. +func runtimeExtensionSpecs() map[string]*catalog.ExtensionSpec { + return map[string]*catalog.ExtensionSpec{ + "redis": {Name: "redis", Kind: catalog.ExtensionKindPECL, Versions: []string{"6.3.0"}}, + "xdebug": {Name: "xdebug", Kind: catalog.ExtensionKindPECL, Versions: []string{"3.5.1"}, Ini: []string{"zend_extension=xdebug"}}, + "pcov": {Name: "pcov", Kind: catalog.ExtensionKindPECL, Versions: []string{"1.0.12"}, Ini: []string{"extension=pcov"}}, + "apcu": {Name: "apcu", Kind: catalog.ExtensionKindPECL, Versions: []string{"5.1.28"}}, + "igbinary": {Name: "igbinary", Kind: catalog.ExtensionKindPECL, Versions: []string{"3.2.16"}}, + "msgpack": {Name: "msgpack", Kind: catalog.ExtensionKindPECL, Versions: []string{"3.0.0"}}, + "uuid": {Name: "uuid", Kind: catalog.ExtensionKindPECL, Versions: []string{"1.3.0"}, RuntimeDeps: map[string][]string{"linux": {"libuuid1"}}}, + "ssh2": {Name: "ssh2", Kind: catalog.ExtensionKindPECL, Versions: []string{"1.5.0"}, RuntimeDeps: map[string][]string{"linux": {"libssh2-1"}}}, + "yaml": {Name: "yaml", Kind: catalog.ExtensionKindPECL, Versions: []string{"2.3.0"}, RuntimeDeps: map[string][]string{"linux": {"libyaml-0-2"}}}, + "memcached": {Name: "memcached", Kind: catalog.ExtensionKindPECL, Versions: []string{"3.4.0"}, RuntimeDeps: map[string][]string{"linux": {"libmemcached11", "libsasl2-2"}}}, + "amqp": {Name: "amqp", Kind: catalog.ExtensionKindPECL, Versions: []string{"2.2.0"}, RuntimeDeps: map[string][]string{"linux": {"librabbitmq4"}}}, + "event": {Name: "event", Kind: catalog.ExtensionKindPECL, Versions: []string{"3.1.4"}, RuntimeDeps: map[string][]string{"linux": {"libevent-2.1-7", "libevent-extra-2.1-7", "libevent-openssl-2.1-7"}}}, + "rdkafka": {Name: "rdkafka", Kind: catalog.ExtensionKindPECL, Versions: []string{"6.0.5"}, RuntimeDeps: map[string][]string{"linux": {"librdkafka1"}}}, + "protobuf": {Name: "protobuf", Kind: catalog.ExtensionKindPECL, Versions: []string{"5.34.1"}}, + "imagick": {Name: "imagick", Kind: catalog.ExtensionKindPECL, Versions: []string{"3.8.1"}, RuntimeDeps: map[string][]string{"linux": {"libfontconfig1", "libx11-6", "libxext6", "liblcms2-2", "liblqr-1-0", "libfftw3-double3", "libbz2-1.0"}}}, + "mongodb": {Name: "mongodb", Kind: catalog.ExtensionKindPECL, Versions: []string{"2.2.1"}, RuntimeDeps: map[string][]string{"linux": {"libssl3", "libsasl2-2"}}}, + "swoole": {Name: "swoole", Kind: catalog.ExtensionKindPECL, Versions: []string{"6.2.0"}, RuntimeDeps: map[string][]string{"linux": {"libssl3", "libcurl4"}}}, + "grpc": {Name: "grpc", Kind: catalog.ExtensionKindPECL, Versions: []string{"1.80.0"}, RuntimeDeps: map[string][]string{"linux": {"libssl3"}}}, + } +} diff --git a/cmd/phpup/runtime_catalog_test.go b/cmd/phpup/runtime_catalog_test.go new file mode 100644 index 0000000..ce00100 --- /dev/null +++ b/cmd/phpup/runtime_catalog_test.go @@ -0,0 +1,61 @@ +package main + +import ( + "fmt" + "path/filepath" + "runtime" + "slices" + "sort" + "testing" + + "github.com/buildrush/setup-php/internal/catalog" +) + +// TestRuntimeExtensionSpecsMatchYAML guards against drift between the inline +// extension specs in runtimeExtensionSpecs() and the authoritative YAML files +// at catalog/extensions/.yaml. Mirrors the pattern used by +// TestCatalogBundledMatchesCompat in internal/catalog/catalog_compat_test.go. +// +// Only version pins and kind are checked; RuntimeDeps and Ini intentionally +// differ in shape between the runtime catalog and the YAML. +func TestRuntimeExtensionSpecsMatchYAML(t *testing.T) { + // Resolve the catalog/extensions directory relative to this test file. + _, thisFile, _, ok := runtime.Caller(0) + if !ok { + t.Fatal("runtime.Caller failed") + } + extDir := filepath.Join(filepath.Dir(thisFile), "..", "..", "catalog", "extensions") + + specs := runtimeExtensionSpecs() + + // Sort keys for deterministic output. + names := make([]string, 0, len(specs)) + for name := range specs { + names = append(names, name) + } + sort.Strings(names) + + for _, name := range names { + inline := specs[name] + yamlPath := filepath.Join(extDir, fmt.Sprintf("%s.yaml", name)) + yamlSpec, err := catalog.LoadExtensionSpec(yamlPath) + if err != nil { + t.Errorf("extension %s: LoadExtensionSpec(%s): %v", name, yamlPath, err) + continue + } + + // Check kind. + if inline.Kind != yamlSpec.Kind { + t.Errorf("extension %s: kind mismatch: inline=%q yaml=%q", name, inline.Kind, yamlSpec.Kind) + } + + // Check versions. + inlineVersions := append([]string(nil), inline.Versions...) + yamlVersions := append([]string(nil), yamlSpec.Versions...) + sort.Strings(inlineVersions) + sort.Strings(yamlVersions) + if !slices.Equal(inlineVersions, yamlVersions) { + t.Errorf("extension %s: versions mismatch: inline=%v yaml=%v", name, inlineVersions, yamlVersions) + } + } +}