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
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,14 @@ jobs:
go-version-file: go.mod
- run: go build ./...
- run: go test ./... -v -race -count=1
wfctl-strict-contracts:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Validate strict plugin contracts
run: go run github.com/GoCodeAlone/workflow/cmd/wfctl@v0.20.1 plugin validate --file plugin.json --strict-contracts
Comment thread
intel352 marked this conversation as resolved.
10 changes: 7 additions & 3 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ version: 2

before:
hooks:
- "cp plugin.json plugin.json.orig"
- "sed -i.bak 's/\"version\": \".*\"/\"version\": \"{{ .Version }}\"/' plugin.json && rm -f plugin.json.bak"
- "mkdir -p dist"
- "cp plugin.json dist/plugin.json"
- "sed -i.bak 's/\"version\": \".*\"/\"version\": \"{{ .Version }}\"/' dist/plugin.json && rm -f dist/plugin.json.bak"
- "sed -i.bak 's|/releases/download/v[^/]*/|/releases/download/v{{ .Version }}/|g' dist/plugin.json && rm -f dist/plugin.json.bak"
- "go run github.com/GoCodeAlone/workflow/cmd/wfctl@v0.20.1 plugin validate --file dist/plugin.json --strict-contracts"

Comment thread
intel352 marked this conversation as resolved.
builds:
- main: ./cmd/{{ .ProjectName }}
Expand All @@ -23,7 +26,8 @@ archives:
- formats: [tar.gz]
name_template: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}"
files:
- plugin.json
- src: dist/plugin.json
dst: plugin.json

checksum:
name_template: checksums.txt
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect
google.golang.org/grpc v1.79.3 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gopkg.in/yaml.v3 v3.0.1
modernc.org/libc v1.67.6 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
Expand Down
164 changes: 118 additions & 46 deletions internal/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,67 @@ var Version = "0.0.0"

type discordPlugin struct{}

type contractDescriptor struct {
Kind string
Type string
Config string
Output string
}

type moduleRegistration struct {
typeName string
config string
create func(name string, config map[string]any) (sdk.ModuleInstance, error)
}

type stepRegistration struct {
typeName string
config string
output string
create func() sdk.StepInstance
}

type triggerRegistration struct {
typeName string
config string
output string
create func(config map[string]any, cb sdk.TriggerCallback) (sdk.TriggerInstance, error)
}

var discordModuleRegistrations = []moduleRegistration{
{
typeName: "discord.provider",
config: "discord.v1.ProviderConfig",
create: func(name string, config map[string]any) (sdk.ModuleInstance, error) {
return newDiscordProvider(name, config)
},
},
}

var discordStepRegistrations = []stepRegistration{
{"step.discord_send_message", "discord.v1.SendMessageConfig", "discord.v1.SendMessageOutput", func() sdk.StepInstance { return &sendMessageStep{} }},
{"step.discord_send_embed", "discord.v1.SendEmbedConfig", "discord.v1.SendEmbedOutput", func() sdk.StepInstance { return &sendEmbedStep{} }},
{"step.discord_edit_message", "discord.v1.EditMessageConfig", "discord.v1.EditMessageOutput", func() sdk.StepInstance { return &editMessageStep{} }},
{"step.discord_delete_message", "discord.v1.DeleteMessageConfig", "discord.v1.DeleteMessageOutput", func() sdk.StepInstance { return &deleteMessageStep{} }},
{"step.discord_add_reaction", "discord.v1.AddReactionConfig", "discord.v1.AddReactionOutput", func() sdk.StepInstance { return &addReactionStep{} }},
{"step.discord_upload_file", "discord.v1.UploadFileConfig", "discord.v1.UploadFileOutput", func() sdk.StepInstance { return &uploadFileStep{} }},
{"step.discord_create_thread", "discord.v1.CreateThreadConfig", "discord.v1.CreateThreadOutput", func() sdk.StepInstance { return &createThreadStep{} }},
{"step.discord_voice_join", "discord.v1.VoiceJoinConfig", "discord.v1.VoiceJoinOutput", func() sdk.StepInstance { return &voiceJoinStep{} }},
{"step.discord_voice_leave", "discord.v1.VoiceLeaveConfig", "discord.v1.VoiceLeaveOutput", func() sdk.StepInstance { return &voiceLeaveStep{} }},
{"step.discord_voice_play", "discord.v1.VoicePlayConfig", "discord.v1.VoicePlayOutput", func() sdk.StepInstance { return &voicePlayStep{} }},
}

var discordTriggerRegistrations = []triggerRegistration{
{
typeName: "trigger.discord",
config: "discord.v1.TriggerConfig",
output: "discord.v1.TriggerPayload",
create: func(config map[string]any, cb sdk.TriggerCallback) (sdk.TriggerInstance, error) {
return newDiscordTrigger(config, cb)
},
},
}

// New returns a new discordPlugin instance.
func New() *discordPlugin { return &discordPlugin{} }

Expand All @@ -29,76 +90,87 @@ func (p *discordPlugin) Manifest() sdk.PluginManifest {

// ModuleTypes returns the module type names this plugin provides.
func (p *discordPlugin) ModuleTypes() []string {
return []string{"discord.provider"}
types := make([]string, 0, len(discordModuleRegistrations))
for _, registration := range discordModuleRegistrations {
types = append(types, registration.typeName)
}
return types
}

// StepTypes returns the step type names this plugin provides.
func (p *discordPlugin) StepTypes() []string {
return []string{
"step.discord_send_message",
"step.discord_send_embed",
"step.discord_edit_message",
"step.discord_delete_message",
"step.discord_add_reaction",
"step.discord_upload_file",
"step.discord_create_thread",
"step.discord_voice_join",
"step.discord_voice_leave",
"step.discord_voice_play",
types := make([]string, 0, len(discordStepRegistrations))
for _, registration := range discordStepRegistrations {
types = append(types, registration.typeName)
}
return types
}

// TriggerTypes returns the trigger type names this plugin provides.
func (p *discordPlugin) TriggerTypes() []string {
return []string{"trigger.discord"}
types := make([]string, 0, len(discordTriggerRegistrations))
for _, registration := range discordTriggerRegistrations {
types = append(types, registration.typeName)
}
return types
}

func (p *discordPlugin) contractDescriptors() []contractDescriptor {
descriptors := make([]contractDescriptor, 0, len(discordModuleRegistrations)+len(discordStepRegistrations)+len(discordTriggerRegistrations))
for _, registration := range discordModuleRegistrations {
descriptors = append(descriptors, contractDescriptor{
Kind: "module",
Type: registration.typeName,
Config: registration.config,
})
}
for _, registration := range discordStepRegistrations {
descriptors = append(descriptors, contractDescriptor{
Kind: "step",
Type: registration.typeName,
Config: registration.config,
Output: registration.output,
})
}
for _, registration := range discordTriggerRegistrations {
descriptors = append(descriptors, contractDescriptor{
Kind: "trigger",
Type: registration.typeName,
Config: registration.config,
Output: registration.output,
})
}
return descriptors
}

// CreateModule creates a module instance of the given type.
func (p *discordPlugin) CreateModule(typeName, name string, config map[string]any) (sdk.ModuleInstance, error) {
switch typeName {
case "discord.provider":
return newDiscordProvider(name, config)
default:
return nil, fmt.Errorf("discord plugin: unknown module type %q", typeName)
for _, registration := range discordModuleRegistrations {
if registration.typeName == typeName {
return registration.create(name, config)
}
}
return nil, fmt.Errorf("discord plugin: unknown module type %q", typeName)
}

// CreateStep creates a step instance of the given type.
func (p *discordPlugin) CreateStep(typeName, name string, config map[string]any) (sdk.StepInstance, error) {
// Steps need access to a provider session; they'll resolve it at Execute time
// via a shared registry keyed by module name.
switch typeName {
case "step.discord_send_message":
return &sendMessageStep{}, nil
case "step.discord_send_embed":
return &sendEmbedStep{}, nil
case "step.discord_edit_message":
return &editMessageStep{}, nil
case "step.discord_delete_message":
return &deleteMessageStep{}, nil
case "step.discord_add_reaction":
return &addReactionStep{}, nil
case "step.discord_upload_file":
return &uploadFileStep{}, nil
case "step.discord_create_thread":
return &createThreadStep{}, nil
case "step.discord_voice_join":
return &voiceJoinStep{}, nil
case "step.discord_voice_leave":
return &voiceLeaveStep{}, nil
case "step.discord_voice_play":
return &voicePlayStep{}, nil
default:
return nil, fmt.Errorf("discord plugin: unknown step type %q", typeName)
for _, registration := range discordStepRegistrations {
if registration.typeName == typeName {
return registration.create(), nil
}
}
return nil, fmt.Errorf("discord plugin: unknown step type %q", typeName)
}

// CreateTrigger creates a trigger instance of the given type.
func (p *discordPlugin) CreateTrigger(typeName string, config map[string]any, cb sdk.TriggerCallback) (sdk.TriggerInstance, error) {
switch typeName {
case "trigger.discord":
return newDiscordTrigger(config, cb)
default:
return nil, fmt.Errorf("discord plugin: unknown trigger type %q", typeName)
for _, registration := range discordTriggerRegistrations {
if registration.typeName == typeName {
return registration.create(config, cb)
}
}
return nil, fmt.Errorf("discord plugin: unknown trigger type %q", typeName)
}
Loading
Loading