- new module kiosk: Manifest, Marshal, Parse, Derive, Generate, Write, Check, StaleError - plugin:manifest [dir] with --check, --pretend, --name, --description - docs: kiosk README, root table row, plugins/marketplace.md, scaffolding row
kiosk
Plugin manifests and the plugin registry contract: generates and checks each plugin's plugin.yaml from its own sources.
import "git.golem15.com/golem15/summercms/modules/kiosk"
Name: A beach kiosk where every plugin on the shelf carries its label; the label is printed from what is in the box, never written by hand.
Overview
A plugin describes itself in plugin.yaml, committed next to its plugin.go. The file is generated: summer plugin:manifest runs kiosk.Write, which reads the plugin's sources and never runs its code. The ID and the required plugins come from what ID() and Requires() in plugin.go return, the module path and the version minimums from go.mod, the package import path from the directory, and the name and description from the README's H1 and the paragraph after it (the standard README structure). The registry on summercms.io reads the same file from every tagged release, and summer build bakes its name and description into the application.
WinterCMS keeps this data in a plugin's Plugin.php pluginDetails() and in composer.json; here it is derived once, so the copy in the repository cannot drift from the code.
Features
- One
plugin.yamlper plugin package directory, so a repository with a nested plugin carries two files. - A schema version (
kiosk.SchemaVersion) and a fixed header line (kiosk.Header); a manifest with a newer schema is refused with a hint to update summer. - Go-style minimums:
frameworkis thego.modrequire ofkiosk.FrameworkModule, and each required plugin gets the version its module is required at. - Name and description overrides (
--name,--description) stored in anoverrides:block that regeneration keeps. kiosk.Checkregenerates in memory and returns akiosk.StaleErrorwhen the committed file is missing or differs, whichsummer plugin:manifest --checkturns into exit status 1.
Usage
path, warnings, err := kiosk.Write(ctx, "plugins/acme/blog", kiosk.DeriveOptions{})
if err != nil {
return err
}
for _, w := range warnings {
log.Println(w)
}
fmt.Println("wrote", path)
if err := kiosk.Check(ctx, "plugins/acme/blog"); err != nil {
var stale *kiosk.StaleError
if errors.As(err, &stale) {
fmt.Printf("expected:\n%s", stale.Want)
}
return err
}
API reference
| Identifier | Description |
|---|---|
kiosk.FileName |
The manifest file name, plugin.yaml. |
kiosk.SchemaVersion |
The newest schema this package reads, and the one it writes. |
kiosk.FrameworkModule |
The framework module path; its go.mod require is the plugin's framework minimum. |
kiosk.Header |
The comment line every generated plugin.yaml starts with. |
kiosk.Manifest |
One plugin.yaml: Schema, ID, Module, Package, Name, Description, Framework, Requires, Overrides, written in that order. |
kiosk.Requires |
Required plugin ID to minimum version; marshals sorted by ID. An empty minimum means the plugin ships in the same module or its module is not a go.mod require. |
kiosk.Requires.MarshalYAML |
Emits the map as a mapping sorted by ID. |
kiosk.Overrides |
The persisted --name and --description values. |
kiosk.Marshal |
The plugin.yaml bytes: the header line, then the fields. |
kiosk.Parse |
Reads plugin.yaml bytes; unknown fields are ignored, a newer schema is an error. |
kiosk.DeriveOptions |
Override changes for kiosk.Derive: nil keeps the persisted value, a pointer to "" clears it. |
kiosk.Derive |
Builds the manifest of a plugin directory from its sources and returns it with warnings. |
kiosk.Generate |
kiosk.Derive plus kiosk.Marshal: the bytes kiosk.Write would write. |
kiosk.Write |
Generates and writes <dir>/plugin.yaml and returns its path. |
kiosk.Check |
Returns a kiosk.StaleError when <dir>/plugin.yaml is missing or differs from a fresh generation. |
kiosk.StaleError |
Path, Missing, and the generated (Want) and committed (Got) bytes; its message names the first differing line. |
CLI commands
| Command | Purpose |
|---|---|
summer plugin:manifest [dir] |
Writes plugin.yaml for the plugin in dir (default: the current directory). --pretend prints it instead, --check fails when the committed file is missing or stale, --name and --description set or (with an empty value) clear the overrides. |
Dependencies
- SummerCMS modules: none.
- Third-party:
github.com/goccy/go-yaml(manifest YAML),github.com/yuin/goldmark(README headings and paragraphs). - Standard library:
bytes,context,encoding/json,errors,fmt,go/ast,go/parser,go/token,os,os/exec,path/filepath,regexp,sort,strconv,strings. - Tools: the
gocommand (go mod edit -json), run without a shell.
Testing
go test ./modules/kiosk/...
TestManifestSmoke copies the fixture plugins in testdata/ to a temporary directory and generates, checks and edits their manifests. The tests run the local go command but need no network and no database.