Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/wfctl/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func runPluginInit(args []string) error {
}
fs := flag.NewFlagSet("plugin init", flag.ExitOnError)
author := fs.String("author", "", "Plugin author (required)")
ver := fs.String("version", "0.1.0", "Plugin version")
ver := fs.String("version", "0.0.0", "Deprecated; release versions are injected from Git tags")
desc := fs.String("description", "", "Plugin description")
license := fs.String("license", "", "Plugin license")
output := fs.String("output", "", "Output directory (defaults to plugin name)")
Expand Down
3 changes: 3 additions & 0 deletions cmd/wfctl/plugin_init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ func TestRunPluginInit_PluginJSON(t *testing.T) {
if pj["version"] == nil || pj["version"].(string) == "" {
t.Error("plugin.json: missing or empty version")
}
if pj["version"].(string) != "0.0.0" {
t.Errorf("version: got %q, want stable plugin.json sentinel %q", pj["version"], "0.0.0")
}
if pj["author"] == nil || pj["author"].(string) == "" {
t.Error("plugin.json: missing or empty author")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,20 @@ jobs:
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: '1.26.4'
- name: Setup wfctl
uses: GoCodeAlone/setup-wfctl@bcd880980f5bbe8d192d0c20ff6279d25331f956 # v1
- name: Validate release contract before packaging
run: wfctl plugin validate-contract --for-publish --tag "${{ "{{" }} github.ref_name {{ "}}" }}" .
- name: Build plugin binaries
run: |
mkdir -p dist
for GOOS in linux darwin; do
for GOARCH in amd64 arm64; do
GOOS=$GOOS GOARCH=$GOARCH go build -o dist/{{.Name}}-$GOOS-$GOARCH ./...
GOOS=$GOOS GOARCH=$GOARCH go build -ldflags "-s -w -X main.Version=${GITHUB_REF_NAME}" -o dist/{{.Name}}-$GOOS-$GOARCH ./...
done
done
- name: Validate packaged release contract
run: wfctl plugin validate-contract --for-publish --tag "${{ "{{" }} github.ref_name {{ "}}" }}" .
- name: Create release
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
with:
Expand Down
4 changes: 3 additions & 1 deletion cmd/wfctl/templates/plugin/main.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ import (
)

func main() {
sdk.Serve(&{{.NameCamel}}Plugin{})
sdk.Serve(&{{.NameCamel}}Plugin{},
sdk.WithBuildVersion(sdk.ResolveBuildVersion(Version)),
)
}
5 changes: 4 additions & 1 deletion cmd/wfctl/templates/plugin/plugin.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ import (
"github.com/GoCodeAlone/workflow/plugin/external/sdk"
)

// Version is injected by the release build so runtime manifests report the tag.
var Version = "dev"

// {{.NameCamel}}Plugin implements sdk.PluginProvider, sdk.ModuleProvider, and sdk.StepProvider.
type {{.NameCamel}}Plugin struct{}

// Manifest returns the plugin metadata.
func (p *{{.NameCamel}}Plugin) Manifest() sdk.PluginManifest {
return sdk.PluginManifest{
Name: "{{.Name}}",
Version: "0.1.0",
Version: sdk.ResolveBuildVersion(Version),
Author: "{{.Author}}",
Description: "{{.Description}}",
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,23 @@ jobs:
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '24'
- name: Setup wfctl
uses: GoCodeAlone/setup-wfctl@bcd880980f5bbe8d192d0c20ff6279d25331f956 # v1
- name: Build UI
run: |
cd ui && npm ci && npm run build && cd ..
- name: Validate release contract before packaging
run: wfctl plugin validate-contract --for-publish --tag "${{ "{{" }} github.ref_name {{ "}}" }}" .
- name: Build plugin binaries
run: |
mkdir -p dist
for GOOS in linux darwin; do
for GOARCH in amd64 arm64; do
GOOS=$GOOS GOARCH=$GOARCH go build -o dist/{{.Name}}-$GOOS-$GOARCH ./...
GOOS=$GOOS GOARCH=$GOARCH go build -ldflags "-s -w -X main.Version=${GITHUB_REF_NAME}" -o dist/{{.Name}}-$GOOS-$GOARCH ./...
done
done
- name: Validate packaged release contract
run: wfctl plugin validate-contract --for-publish --tag "${{ "{{" }} github.ref_name {{ "}}" }}" .
- name: Create release
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
with:
Expand Down
4 changes: 3 additions & 1 deletion cmd/wfctl/templates/ui-plugin/main.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ import (
)

func main() {
sdk.Serve(&{{.NameCamel}}Plugin{})
sdk.Serve(&{{.NameCamel}}Plugin{},
sdk.WithBuildVersion(sdk.ResolveBuildVersion(Version)),
)
}
5 changes: 4 additions & 1 deletion cmd/wfctl/templates/ui-plugin/plugin.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import (
"github.com/GoCodeAlone/workflow/plugin/external/sdk"
)

// Version is injected by the release build so runtime manifests report the tag.
var Version = "dev"

//go:embed ui/dist
var uiAssets embed.FS

Expand All @@ -18,7 +21,7 @@ type {{.NameCamel}}Plugin struct{}
func (p *{{.NameCamel}}Plugin) Manifest() sdk.PluginManifest {
return sdk.PluginManifest{
Name: "{{.Name}}",
Version: "0.1.0",
Version: sdk.ResolveBuildVersion(Version),
Author: "{{.Author}}",
Description: "{{.Description}}",
}
Expand Down
8 changes: 8 additions & 0 deletions plugin/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Package plugin contains Workflow's plugin manifest, registry, loading, and
// installation primitives.
//
// Host-side code normally starts with PluginManifest values loaded from
// plugin.json files, then uses Manager, Loader, or Registry implementations to
// resolve plugin metadata and executables. Plugin authors usually consume the
// higher-level packages under plugin/external/sdk and plugin/sdk instead.
package plugin
16 changes: 16 additions & 0 deletions plugin/external/sdk/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Package sdk is the public runtime SDK for out-of-process Workflow plugins.
//
// Plugin binaries implement PluginProvider plus optional provider interfaces
// such as StepProvider, TypedStepProvider, ModuleProvider, ContractProvider, or
// CLIProvider. A typical main function constructs the provider and calls Serve:
//
// func main() {
// sdk.Serve(internal.NewProvider(),
// sdk.WithBuildVersion(sdk.ResolveBuildVersion(internal.Version)),
// )
// }
//
// Plugins that also expose CLI commands or build hooks can use ServePluginFull.
// IaC provider plugins should use ServeIaCPlugin so typed IaC gRPC services are
// registered and advertised consistently.
package sdk
47 changes: 37 additions & 10 deletions plugin/external/sdk/interfaces.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// Package sdk provides the public API for building external workflow plugins.
// Plugin authors implement the interfaces defined here and call Serve() to run.
package sdk

import (
Expand All @@ -10,7 +8,7 @@ import (
"google.golang.org/protobuf/types/known/anypb"
)

// PluginProvider is the main interface plugin authors implement.
// PluginProvider is the minimum interface every external plugin implements.
type PluginProvider interface {
// Manifest returns the plugin's metadata.
Manifest() PluginManifest
Expand All @@ -21,14 +19,24 @@ type ContractProvider interface {
ContractRegistry() *pb.ContractRegistry
}

// PluginManifest describes the plugin.
// PluginManifest is the runtime metadata a plugin returns to the host.
//
// For release-built plugins, prefer sdk.WithBuildVersion with
// ResolveBuildVersion so Version reflects the Git tag injected by the build
// instead of the committed plugin.json sentinel.
type PluginManifest struct {
Name string
Version string
Author string
Description string
ConfigMutable bool // whether tenants can override the config fragment
SampleCategory string // non-empty means this is a sample/app plugin
// Name is the canonical plugin name, usually workflow-plugin-<short-name>.
Name string
// Version is the operator-visible runtime version.
Version string
// Author identifies the organization or person that maintains the plugin.
Author string
// Description is shown in registry and documentation output.
Description string
// ConfigMutable reports whether tenants can override the config fragment.
ConfigMutable bool
// SampleCategory marks sample/app plugins for grouped presentation.
SampleCategory string
}

// AssetProvider allows plugins to serve embedded static assets (e.g., UI files).
Expand Down Expand Up @@ -163,13 +171,32 @@ type TypedServiceInvoker interface {
InvokeTypedMethod(method string, input *anypb.Any) (*anypb.Any, error)
}

// TelemetryAttrs aliases the host telemetry attribute map type for plugin APIs.
type TelemetryAttrs = telemetry.Attrs

// TelemetryMetricKind aliases the host metric kind enum for plugin APIs.
type TelemetryMetricKind = telemetry.MetricKind

// TelemetryMetricRecord aliases the host metric record type for plugin APIs.
type TelemetryMetricRecord = telemetry.MetricRecord

// TelemetryMetricRecorder aliases the host metric recorder interface for plugin APIs.
type TelemetryMetricRecorder = telemetry.MetricRecorder

// TelemetryMetricEmitter aliases the host metric emitter interface for plugin APIs.
type TelemetryMetricEmitter = telemetry.MetricEmitter

// TelemetryLogRecord aliases the host log record type for plugin APIs.
type TelemetryLogRecord = telemetry.LogRecord

// TelemetryLogEmitter aliases the host log emitter interface for plugin APIs.
type TelemetryLogEmitter = telemetry.LogEmitter

// TelemetrySpanEvent aliases the host span event type for plugin APIs.
type TelemetrySpanEvent = telemetry.SpanEvent

// TelemetrySpanRecorder aliases the host span recorder interface for plugin APIs.
type TelemetrySpanRecorder = telemetry.SpanRecorder

// TelemetryTraceAnnotator aliases the host trace annotator interface for plugin APIs.
type TelemetryTraceAnnotator = telemetry.TraceAnnotator
8 changes: 8 additions & 0 deletions plugin/sdk/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Package sdk contains authoring tools for Workflow plugins.
//
// The package is used by wfctl plugin init and by tests that need to generate
// realistic plugin repositories. TemplateGenerator creates a buildable plugin
// project with plugin.json, Go code, release workflows, GoReleaser metadata,
// and contract descriptor files. Runtime plugin binaries should use
// github.com/GoCodeAlone/workflow/plugin/external/sdk.
package sdk
Loading
Loading