Skip to content

feat(cli): wheels packages CLI — registry-backed install (#2270 Phase 3)#2276

Merged
bpamiri merged 2 commits intodevelopfrom
claude/keen-jemison-9855ee
Apr 24, 2026
Merged

feat(cli): wheels packages CLI — registry-backed install (#2270 Phase 3)#2276
bpamiri merged 2 commits intodevelopfrom
claude/keen-jemison-9855ee

Conversation

@bpamiri
Copy link
Copy Markdown
Collaborator

@bpamiri bpamiri commented Apr 24, 2026

Summary

Phase 3 of #2243 — ships the consumer CLI for the wheels-packages registry that Phase 1 (#2266) and Phase 2 set up. Users can now wheels packages install wheels-sentry and have it appear under vendor/ with the tarball sha256 verified against the registry's manifest, no ForgeBox or CommandBox involved.

What's new

Eight verbs under wheels packages:

wheels packages list [--tag=<tag>]
wheels packages search <query>
wheels packages show <name>
wheels packages install <name>[@<version>] [--force]
wheels packages update <name> --yes
wheels packages update --all --yes
wheels packages remove <name>
wheels packages registry refresh
wheels packages registry info

WHEELS_PACKAGES_REGISTRY=<org>/<repo> env var overrides the default registry — useful for forks, mirrors, and test registries.

Architecture

Six components in cli/lucli/services/packages/, each independently testable:

File Purpose
HttpClient.cfc cfhttp wrapper, injectable for offline tests
ManifestCache.cfc 24h FS cache at ~/.wheels/cache/packages/
Registry.cfc GitHub contents API + raw.githubusercontent.com client
VersionResolver.cfc Reuses vendor/wheels/SemVer.cfc (from #2231)
Installer.cfc Download → sha256 verify → tar -xzf into vendor/<name>/
PackagesMainCli.cfc / PackagesRegistryCli.cfc User-facing dispatchers

Design decisions locked in

  • SHA-256 mismatch = hard abort. No --skip-checksum flag. This is the whole point of the registry-hosted-tarball design (defeats Attack A — force-push / tag rewrite).
  • Explicit-only updates. update <name> and update --all require --yes. No auto-pull on reload (Attack B defense).
  • Install refuses collisions. vendor/<name>/ must not exist; --force to overwrite.
  • update --all continues on failure. Aggregates per-package results, exits non-zero if any failed (matches dnf update / apt upgrade / npm update).
  • Tarball extraction shells out to tar. All target platforms ship it (macOS, Linux, Windows 10+). If Windows Server compat ever matters, swap the $extract() body for a Commons Compress JAR without changing the Installer interface.

Tests

22 new specs under cli/lucli/tests/specs/packages/. All network-free — they use a FakeHttpClient stub and a committed fixture tarball (wheels-fake-1.0.0.tar.gz) at cli/lucli/tests/_fixtures/packages/.

  • VersionResolverSpec — 7 cases covering pin + wheelsVersion filtering, highest-wins, empty-versions, compatibleVersions ordering.
  • ManifestCacheSpec — 6 cases covering round-trip read/write, TTL expiry, refresh, info.
  • RegistrySpec — 7 cases covering list, cache reuse, manifest fetch, 404, 500, info, env fallback.
  • InstallerSpec — 8 cases covering happy path, checksum mismatch, force overwrite, missing tarball, uninstall safety.
  • PackagesMainCliSpec + PackagesRegistryCliSpec — 13 cases covering every CLI verb end-to-end against the fake stack.

Docs

  • web/sites/guides/src/content/docs/v4-0-0-snapshot/command-line-tools/commands/packages/ — 8 mdx files (index + per-verb).
  • CLAUDE.md — Package System section updated to point at the new CLI instead of the gh repo clone interim.

Out of scope

  • Phase 4 web UI (separate issue).
  • Private/enterprise registries (design spec defers this).
  • Dependency resolution between packages (design spec: v5.0).
  • Removing per-file checksums from PackageLoader.cfc (design spec P9 — separate issue).
  • Windows Server compat verification. tar.exe ships on Windows 10+ so it should work; I didn't test it.

Test plan

  • bash tools/test-cli-local.sh — 429 pass, 0 fail, 0 error
  • bash tools/test-local.sh — 3319 core framework tests pass
  • CI compat matrix green across Lucee 5/6/7 + Adobe 2018/2021/2023/2025 + BoxLang
  • Guide site build green (npm run build in web/sites/guides/)
  • Smoke-test wheels packages list against real registry once next LuCLI snapshot is built

Follow-ups

  • Registry ships an aggregated index.json so list is one HTTP round-trip instead of N+1 (Phase 3.5, registry-side).
  • Phase 4 — web UI for wheels.dev/packages + in-app /wheels/packages.
  • Retire per-file checksums from PackageLoader.cfc now that distribution-layer sha256 is authoritative.

…2270 Phase 3)

Phase 3 of #2243. Adds `wheels packages list|search|show|install|update|remove`
plus `wheels packages registry refresh|info` over the wheels-packages registry.

- Registry client with 24h FS cache keyed at ~/.wheels/cache/packages/
- Installer: HTTPS download, SHA-256 verify against manifest, tar -xzf into
  vendor/<name>/. Hard-aborts on checksum mismatch; refuses overwrite
  without --force.
- VersionResolver reuses vendor/wheels/SemVer.cfc (shipped in #2231) so
  the CLI and PackageLoader agree on wheelsVersion satisfaction.
- Explicit-only updates: `update <name>` and `update --all` require --yes.
  `update --all` continues on per-package failures and throws at the end
  so the shell exit code reflects partial failure.
- WHEELS_PACKAGES_REGISTRY env var overrides the default registry repo.
- Docs: web/sites/guides/.../command-line-tools/commands/packages/ and
  CLAUDE.md Package System section updated.
- 22 new specs under cli/lucli/tests/specs/packages/, network-free via
  FakeHttpClient + a fixture tarball.
@github-actions github-actions Bot added the docs label Apr 24, 2026
…X build

MDX parses bare `<2.0.0` as a JSX tag (`Unexpected character `2`
before name`). Wrap the compatible-with range in backticks so the MDX
rollup plugin treats it as code.
@bpamiri bpamiri merged commit 110f95d into develop Apr 24, 2026
10 checks passed
@bpamiri bpamiri deleted the claude/keen-jemison-9855ee branch April 24, 2026 00:29
bpamiri added a commit that referenced this pull request Apr 24, 2026
* docs(docs): update packages guide for accuracy and 4.1 reality

Closes #2244.

The packages.mdx guide was shipped before several key pieces landed: the
`wheels packages` CLI, the wheels-i18n and wheels-seo-suite conversions
to 4.0 format, and before the `view` mixin-target claim was noticed as
unsupported. This refresh brings the guide into sync with reality.

Substantive changes to `packages.mdx`:

- Remove `view` and `service` from the `provides.mixins` target list —
  neither is in PackageLoader's allowlist
  (application,dispatch,controller,mapper,model,base,sqlserver,mysql,
  postgresql,h2,test plus the specials global/none). Explain that
  `controller` already covers views since Wheels views run in the
  controller's variables scope.
- Replace the per-method override example's `mixin="view"` with realistic
  `mixin="model"` and `mixin="none"` examples.
- Replace "Until Wheels 4.1 lands / gh repo clone as interim" with the
  real `wheels packages install|list|search|show|update|remove|registry`
  CLI that shipped in #2276.
- Update first-party package list: drop "wheels-i18n is planned for
  conversion" (shipped as v2.0.0) and add both wheels-i18n and
  wheels-seo-suite to the list of shipped packages.
- Add dedicated sections: Service providers (register/boot lifecycle
  with ServiceProviderInterface) and Lazy loading (the `lazy: true`
  manifest flag for service-only packages).
- Rewrite the testing section: replace the broken `directory=vendor.*`
  URL-param pattern (tracked by #2280) with a BDD spec example and a
  caution box pointing at the issue, plus guidance to rely on
  per-package CI.
- Rewrite the publishing section with the actual registry submission
  checklist and flow (public repo, v<version> tag, file-type allowlist,
  10 MB cap, PR title, mirror workflow bot-commits tarball+sha256).
- Add a `lazy` field entry and mention `dependencies` ordering more
  explicitly in the manifest reference.

Smaller fixes:

- `glossary.mdx`: "Mixin target" entry no longer lists the non-existent
  `view` target.
- `upgrading/3x-to-4x.mdx`: update `mixin="view"` annotation example to
  `mixin="model"` / `mixin="none"`.
- `CLAUDE.md`: add a cross-link to the public packages guide and to
  wheels-packages/CONTRIBUTING.md, and refresh the first-party package
  list to include wheels-i18n and wheels-seo-suite.

No code changes — docs and instructions only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(docs): refresh packages-index visual baseline

The /packages landing page now renders wheels-i18n and wheels-seo-suite
tiles alongside the original four first-party packages (shipped earlier
today via wheels-dev/wheels-packages#3 and #4, closes #2268 and #2267).

The existing baseline predates those registry entries, so visual-regression
reports 34,529 pixels differ. Diff reviewed — only the two new package
tiles; layout, typography, header, and existing tiles unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant