feat(kiosk): plugin.yaml manifest and summer plugin:manifest
- 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
This commit is contained in:
@@ -3,9 +3,11 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
@@ -13,6 +15,7 @@ import (
|
||||
"git.golem15.com/golem15/summercms/internal/dev"
|
||||
"git.golem15.com/golem15/summercms/modules/bonfire"
|
||||
"git.golem15.com/golem15/summercms/modules/diary"
|
||||
"git.golem15.com/golem15/summercms/modules/kiosk"
|
||||
"git.golem15.com/golem15/summercms/modules/lagoon"
|
||||
)
|
||||
|
||||
@@ -38,6 +41,7 @@ func toolCommands() []bonfire.Command {
|
||||
makeJobCommand(),
|
||||
makeAdminControllerCommand(),
|
||||
addPluginCommand(),
|
||||
pluginManifestCommand(),
|
||||
newCommand(),
|
||||
devCommand(),
|
||||
parityProxyCommand(),
|
||||
@@ -414,6 +418,92 @@ already registered is an error.`,
|
||||
}
|
||||
}
|
||||
|
||||
func pluginManifestCommand() bonfire.Command {
|
||||
return bonfire.Command{
|
||||
Name: "plugin:manifest",
|
||||
Description: "Generate or check a plugin's plugin.yaml from its sources",
|
||||
Long: `Writes plugin.yaml into a plugin directory (the current one by default). Every
|
||||
field comes from the plugin's own sources: the ID and the required plugins
|
||||
from what plugin.go's ID() and Requires() return (string literals or
|
||||
constants, read without running any code), the module path and the framework
|
||||
and plugin 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. plugin.yaml is committed next to plugin.go and never
|
||||
edited by hand: rerun the command after changing any of those sources.
|
||||
|
||||
--name and --description replace the README text and are kept in plugin.yaml
|
||||
until changed again; --name="" clears the override. A README whose H1 is the
|
||||
plugin ID needs --name. --pretend prints the file without writing it.
|
||||
--check writes nothing and exits 1, printing the expected content, when
|
||||
plugin.yaml is missing or differs from what the command would write.`,
|
||||
Examples: []bonfire.Example{
|
||||
{Command: "plugin:manifest plugins/acme/blog", Description: "Write plugins/acme/blog/plugin.yaml"},
|
||||
{Command: "plugin:manifest --check", Description: "Fail when the current directory's plugin.yaml is missing or stale"},
|
||||
{Command: "plugin:manifest --pretend", Description: "Print the manifest without writing it"},
|
||||
{Command: `plugin:manifest --name="Blog"`, Description: "Use Blog as the display name instead of the README's H1"},
|
||||
},
|
||||
Args: []bonfire.Arg{{
|
||||
Name: "dir",
|
||||
Description: "Plugin directory, the one with plugin.go (default: the current directory)",
|
||||
}},
|
||||
Flags: []bonfire.Flag{
|
||||
{Name: "check", Description: "Write nothing; exit 1 when plugin.yaml is missing or stale", Bare: true},
|
||||
{Name: "pretend", Description: "Print the generated plugin.yaml instead of writing it", Bare: true},
|
||||
{Name: "name", Description: "Display name override, kept in plugin.yaml; an empty value clears it"},
|
||||
{Name: "description", Description: "Description override, kept in plugin.yaml; an empty value clears it"},
|
||||
},
|
||||
Run: func(ctx context.Context, in bonfire.Input, out bonfire.Output) error {
|
||||
dir, ok := in.Argument("dir")
|
||||
if !ok || dir == "" {
|
||||
dir = "."
|
||||
}
|
||||
var opts kiosk.DeriveOptions
|
||||
if v, ok := in.Flag("name"); ok {
|
||||
opts.Name = &v
|
||||
}
|
||||
if v, ok := in.Flag("description"); ok {
|
||||
opts.Description = &v
|
||||
}
|
||||
if bonfire.FlagBool(in, "check") {
|
||||
if opts.Name != nil || opts.Description != nil {
|
||||
return fmt.Errorf("plugin:manifest --check takes no --name or --description; run plugin:manifest without --check to change them")
|
||||
}
|
||||
err := kiosk.Check(ctx, dir)
|
||||
var stale *kiosk.StaleError
|
||||
if errors.As(err, &stale) {
|
||||
out.Println("Expected " + stale.Path + ":")
|
||||
out.Println(strings.TrimRight(string(stale.Want), "\n"))
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out.Success(filepath.Join(dir, kiosk.FileName) + " is up to date")
|
||||
return nil
|
||||
}
|
||||
if bonfire.FlagBool(in, "pretend") {
|
||||
data, warnings, err := kiosk.Generate(ctx, dir, opts)
|
||||
for _, w := range warnings {
|
||||
out.Warning(w)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out.Println(strings.TrimRight(string(data), "\n"))
|
||||
return nil
|
||||
}
|
||||
path, warnings, err := kiosk.Write(ctx, dir, opts)
|
||||
for _, w := range warnings {
|
||||
out.Warning(w)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out.Success("Wrote " + path)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newCommand() bonfire.Command {
|
||||
return bonfire.Command{
|
||||
Name: "new",
|
||||
|
||||
Reference in New Issue
Block a user