plugins API

plugins

package

API reference for the plugins package.

I
interface

Plugin

Plugin defines the minimal interface that build plugins must implement.

cmd/rfw/plugins/plugins.go:10-14
type Plugin interface

Methods

Name
Method

Returns

string
func Name(...)
ShouldRebuild
Method

Parameters

path string

Returns

bool
func ShouldRebuild(...)
Priority
Method

Returns

int
func Priority(...)
I
interface

PreBuilder

PreBuilder is implemented by plugins that run before the build.

cmd/rfw/plugins/plugins.go:17-17
type PreBuilder interface

Methods

PreBuild
Method

Parameters

Returns

error
func PreBuild(...)
I
interface

Builder

Builder is implemented by plugins that participate in the build step.

cmd/rfw/plugins/plugins.go:20-20
type Builder interface

Methods

Build
Method

Parameters

Returns

error
func Build(...)
I
interface

PostBuilder

PostBuilder is implemented by plugins that run after the build completes.

cmd/rfw/plugins/plugins.go:23-23
type PostBuilder interface

Methods

PostBuild
Method

Parameters

Returns

error
func PostBuild(...)
S
struct

entry

cmd/rfw/plugins/plugins.go:25-28
type entry struct

Fields

Name Type Description
Plugin Plugin
cfg json.RawMessage
S
struct

Info

Info reports the name and configuration of an active plugin.

cmd/rfw/plugins/plugins.go:36-39
type Info struct

Fields

Name Type Description
Name string json:"name"
Config json.RawMessage json:"config"
F
function

Active

Active returns the list of configured plugins in execution order.

Returns

cmd/rfw/plugins/plugins.go:42-48
func Active() []Info

{
	out := make([]Info, len(active))
	for i, e := range active {
		out[i] = Info{Name: e.Plugin.Name(), Config: e.cfg}
	}
	return out
}
F
function

Register

Register adds a plugin to the registry.

Parameters

p
cmd/rfw/plugins/plugins.go:51-51
func Register(p Plugin)

{ registry[p.Name()] = p }
F
function

Install

Install activates a single plugin by name.

Parameters

name
string

Returns

error
cmd/rfw/plugins/plugins.go:54-60
func Install(name string, raw json.RawMessage) error

{
	if p, ok := registry[name]; ok {
		active = append(active, entry{Plugin: p, cfg: raw})
		return nil
	}
	return fmt.Errorf("plugin %s not found", name)
}
F
function

Configure

Configure installs plugins from the provided configuration map.

Parameters

cfg
map[string]json.RawMessage

Returns

error
cmd/rfw/plugins/plugins.go:63-74
func Configure(cfg map[string]json.RawMessage) error

{
	active = active[:0]
	for name, raw := range cfg {
		if err := Install(name, raw); err != nil {
			return err
		}
	}
	sort.SliceStable(active, func(i, j int) bool {
		return active[i].Plugin.Priority() < active[j].Plugin.Priority()
	})
	return nil
}
F
function

NeedsRebuild

NeedsRebuild reports whether any active plugin requires a rebuild for the given path.

Parameters

path
string

Returns

bool
cmd/rfw/plugins/plugins.go:77-84
func NeedsRebuild(path string) bool

{
	for _, e := range active {
		if e.Plugin.ShouldRebuild(path) {
			return true
		}
	}
	return false
}
F
function

PreBuild

PreBuild calls PreBuild on all plugins that implement PreBuilder.

Returns

error
cmd/rfw/plugins/plugins.go:87-96
func PreBuild() error

{
	for _, e := range active {
		if pb, ok := e.Plugin.(PreBuilder); ok {
			if err := pb.PreBuild(e.cfg); err != nil {
				return fmt.Errorf("%s prebuild: %w", e.Plugin.Name(), err)
			}
		}
	}
	return nil
}
F
function

Build

Build calls Build on all plugins that implement Builder.

Returns

error
cmd/rfw/plugins/plugins.go:99-108
func Build() error

{
	for _, e := range active {
		if b, ok := e.Plugin.(Builder); ok {
			if err := b.Build(e.cfg); err != nil {
				return fmt.Errorf("%s build: %w", e.Plugin.Name(), err)
			}
		}
	}
	return nil
}
F
function

PostBuild

PostBuild calls PostBuild on all plugins that implement PostBuilder.

Returns

error
cmd/rfw/plugins/plugins.go:111-120
func PostBuild() error

{
	for _, e := range active {
		if pb, ok := e.Plugin.(PostBuilder); ok {
			if err := pb.PostBuild(e.cfg); err != nil {
				return fmt.Errorf("%s postbuild: %w", e.Plugin.Name(), err)
			}
		}
	}
	return nil
}
S
struct

mockPlugin

mockPlugin is a simple implementation of the Plugin interface used for
testing the plugin registry and lifecycle.

cmd/rfw/plugins/plugins_test.go:10-17
type mockPlugin struct

Methods

Name
Method

Returns

string
func (*mockPlugin) Name() string
{ return m.name }
Priority
Method

Returns

int
func (*mockPlugin) Priority() int
{ return m.priority }
ShouldRebuild
Method

Parameters

p string

Returns

bool
func (*mockPlugin) ShouldRebuild(p string) bool
{ return p == m.rebuild }
PreBuild
Method

Parameters

Returns

error
func (*mockPlugin) PreBuild(json.RawMessage) error
{
	m.pre = true
	return nil
}
Build
Method

Parameters

Returns

error
func (*mockPlugin) Build(json.RawMessage) error
{
	m.build = true
	return nil
}
PostBuild
Method

Parameters

Returns

error
func (*mockPlugin) PostBuild(json.RawMessage) error
{
	m.post = true
	return nil
}

Fields

Name Type Description
name string
priority int
rebuild string
pre bool
build bool
post bool
F
function

TestLifecycle

TestLifecycle verifies registration, ordering and lifecycle invocation of
plugins as well as the NeedsRebuild helper.

Parameters

cmd/rfw/plugins/plugins_test.go:37-80
func TestLifecycle(t *testing.T)

{
	// Reset global state.
	registry = map[string]Plugin{}
	active = nil

	p1 := &mockPlugin{name: "p1", priority: 1, rebuild: "a.go"}
	p0 := &mockPlugin{name: "p0", priority: 0}
	Register(p1)
	Register(p0)

	cfg := map[string]json.RawMessage{"p1": nil, "p0": nil}
	if err := Configure(cfg); err != nil {
		t.Fatalf("configure: %v", err)
	}
	if len(active) != 2 || active[0].Plugin != p0 || active[1].Plugin != p1 {
		t.Fatalf("plugins not sorted by priority: %#v", active)
	}

	if err := PreBuild(); err != nil {
		t.Fatalf("prebuild: %v", err)
	}
	if !p1.pre || !p0.pre {
		t.Fatalf("prebuild not invoked")
	}
	if err := Build(); err != nil {
		t.Fatalf("build: %v", err)
	}
	if !p1.build || !p0.build {
		t.Fatalf("build not invoked")
	}
	if err := PostBuild(); err != nil {
		t.Fatalf("postbuild: %v", err)
	}
	if !p1.post || !p0.post {
		t.Fatalf("postbuild not invoked")
	}

	if !NeedsRebuild("a.go") {
		t.Fatalf("expected rebuild for a.go")
	}
	if NeedsRebuild("b.go") {
		t.Fatalf("unexpected rebuild for b.go")
	}
}
F
function

TestActive

Parameters

cmd/rfw/plugins/plugins_test.go:82-97
func TestActive(t *testing.T)

{
	registry = map[string]Plugin{}
	active = nil

	p := &mockPlugin{name: "p", priority: 0}
	Register(p)

	cfg := map[string]json.RawMessage{"p": json.RawMessage("{\"x\":1}")}
	if err := Configure(cfg); err != nil {
		t.Fatalf("configure: %v", err)
	}
	list := Active()
	if len(list) != 1 || list[0].Name != "p" || string(list[0].Config) != "{\"x\":1}" {
		t.Fatalf("unexpected active list: %#v", list)
	}
}