feat(build): summer plugin:install for registry plugins as Go modules
- kiosk.Client reads the registry API v1 over fetchguard (trusted mode, 4 MiB, 10 s, no redirects); kiosk.RegistryURL reads plugins.registry_url (default https://summercms.io, empty disables) - build.PlanInstall/ApplyInstall pick the newest release the effective framework satisfies (or a pin), validate registry strings, go get it and append it to summer.yaml - summer.yaml edits (plugin:add and plugin:install) keep comments and blank lines - TestInstallSmoke/module installs from a file:// GOPROXY and builds
This commit is contained in:
@@ -109,6 +109,7 @@ summer plugin:add plugins/acme/blog
|
||||
|---------|---------|
|
||||
| `summer plugin:add` | Registers a local plugin directory: `summer.yaml`, a `require` and a local `replace` in `go.mod`, and `go.work`. |
|
||||
| `summer plugin:manifest` | Writes the plugin's `plugin.yaml` from its sources (`plugin.go`, `go.mod`, the README). `--pretend` prints it, `--check` exits 1 when the committed file is missing or stale, `--name` and `--description` override the README text. See [Publishing plugins](../plugins/marketplace.md). |
|
||||
| `summer plugin:install` | Installs a plugin by ID (`acme.blog`, or pinned `acme.blog@v0.3.0`) from the registry as a Go module: the newest release the application's framework version meets, after printing it and asking (`--yes` skips the question). See [Installing plugins](../plugins/marketplace.md#installing-plugins). |
|
||||
|
||||
## Generating plugin parts
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Publishing plugins
|
||||
description: Describe a plugin for the marketplace with a generated plugin.yaml, keep it current with summer plugin:manifest --check, and read the registry API.
|
||||
description: Describe a plugin with a generated plugin.yaml, install listed plugins with summer plugin:install, and read the registry API.
|
||||
section: plugins
|
||||
order: 50
|
||||
---
|
||||
@@ -92,6 +92,35 @@ func TestPluginManifest(t *testing.T) {
|
||||
|
||||
`summer build` reads the `plugin.yaml` of every plugin the application lists and bakes the name and description into the generated `plugins.gen.go` as `PluginInfo`, next to each plugin's version and the framework version (`FrameworkVersion`). At start-up the application publishes them as `party.Installed`, which the admin's Plugins screen reads. [Go modules and workspaces](../architecture/go-modules-and-workspaces.md#the-summeryaml-manifest) explains where the versions come from.
|
||||
|
||||
## Installing plugins
|
||||
|
||||
`summer plugin:install` adds a listed plugin to an application. Run it inside the application:
|
||||
|
||||
```sh
|
||||
summer plugin:install acme.blog
|
||||
summer plugin:install acme.blog@v0.3.0
|
||||
summer plugin:install acme.blog --yes
|
||||
```
|
||||
|
||||
The command asks the registry for the plugin's releases and picks the newest one whose framework minimum the application meets. The application's framework version is the effective one: the newest tag of a local framework checkout when `go.mod` or `go.work` replaces the framework with a directory, otherwise the version `go.mod` requires. `@vX.Y.Z` pins a release, which must meet the framework minimum too. When every release needs a newer framework, the command stops and names the framework version to move to; it never changes the framework requirement itself.
|
||||
|
||||
The plugin is installed as a Go module: one `go get <module>@<version>` in the application, then an entry with its ID and package in `summer.yaml`. The edit appends to the `plugins:` list and keeps the file's comments and blank lines. Run `summer build` afterwards: it generates the import, and the new require in `go.mod` loses its `// indirect` marker the next time you run `go mod tidy`. A plugin that is already in `summer.yaml` is not installed again.
|
||||
|
||||
Before changing anything, the command prints each plugin it is about to add as `id@version (module)` and asks for confirmation. `--yes` skips the question. A run that cannot ask (no terminal, `-n` or `-q`) stops with an error unless `--yes` is given.
|
||||
|
||||
### The registry setting
|
||||
|
||||
The registry is `https://summercms.io` unless the application's `plugins.registry_url` setting names another one:
|
||||
|
||||
```yaml
|
||||
# config/plugins.yaml
|
||||
registry_url: https://registry.example.com
|
||||
```
|
||||
|
||||
The environment variable `SUMMER_PLUGINS__REGISTRY_URL` overrides the file. The value must be the final origin, because the client does not follow redirects. An empty value disables registry calls: installs by ID then fail, and the admin's Plugins screen shows only installed plugins. `--offline` disables registry calls for one run.
|
||||
|
||||
Every registry call goes through `kiosk.Client`, which uses `fetchguard` with a 10 second timeout and a 4 MiB limit on the answer. Module paths, package paths and versions from the registry are checked (a plain module path, a strict `vX.Y.Z` version) before any `go` command runs.
|
||||
|
||||
## Registry API v1
|
||||
|
||||
summercms.io publishes the plugins it lists through a read-only JSON API. The marketplace pages, `summer` and the admin's Plugins screen read it. Its base path is `/api/registry/v1` (`kiosk.RegistryAPIPath`), and the `kiosk` module holds its wire types, so every client and the server share one definition of the shape.
|
||||
|
||||
Reference in New Issue
Block a user