This is a SCAFFOLD repo. It is NOT an installable plugin.
Use it to create a new workflow plugin via GitHub's "Use this template" button.
(A future wfctl plugin init --from-scaffold subcommand is tracked at
workflow#762 but
not yet implemented; use the GitHub UI path below.)
-
Enable GitHub Actions: Settings → Actions → "I understand my workflows, enable them". New repos created from a template ship with workflows DISABLED by default; you must enable them once before any release.yml run can succeed.
-
Run the rename script:
bash scripts/rename-from-scaffold.sh <your-plugin-name> --mode [iac|non-iac]
This:
- Picks the IaC or non-IaC main.go variant; deletes the other.
- Renames
cmd/scaffold-workflow-plugin*/→cmd/workflow-plugin-<your-name>/. - Updates
go.modmodule path. - Bulk-sed of
scaffold-workflow-plugin→workflow-plugin-<your-name>across.go/.yaml/.md/plugin.jsonfiles. - Resets
plugin.json.typefrom"scaffold"to"external"; sets.name. - Removes the rename script itself + scaffold-rename-test workflow.
-
Edit
plugin.json: replaceTEMPLATE.module/TEMPLATE.step/TEMPLATE.resourceplaceholder capabilities with your plugin's actual types. UpdateminEngineVersionif you depend on a newer workflow. -
Implement your plugin in
internal/:- non-IaC mode: extend
internal/plugin.go'sNewPlugin()with real ModuleFactories / StepFactories / TriggerFactories. Deleteinternal/iacserver.go(unused in non-IaC mode). - IaC mode: replace
internal/iacserver.go's stubpb.UnimplementedIaCProviderRequiredServerembed with your real IaC provider implementation (Initialize, Plan, Destroy, etc.). Deleteinternal/plugin.go's NewPlugin (unused in IaC mode).
- non-IaC mode: extend
-
Commit + tag:
git add -A && git commit -m "feat: initial plugin scaffold from scaffold-workflow-plugin" git tag v0.1.0 && git push origin main v0.1.0
release.yml'swfctl plugin validate-contract --for-publishgate verifies your tag (must be release-grade semver^v\d+\.\d+\.\d+$) and contract (capabilities populated, minEngineVersion set, main.go wiressdk.ResolveBuildVersion, goreleaser ldflag present).
--mode non-iac(default): for module/step/trigger plugins that usesdk.Serve. Suitable for MOST plugins.--mode iac: for IaC provider plugins that usesdk.ServeIaCPluginand satisfypb.IaCProviderRequiredServer. Use ONLY if your plugin provisions infrastructure (cloud resources, databases, etc.).
plugin.json.version = "0.0.0"sentinel (release tag injected at build time via goreleaser).internal/plugin.go'svar Version = "0.0.0"(ldflag-injected at release; surfaced throughsdk.ResolveBuildVersion).release.ymlpre-build + post-buildwfctl plugin validate-contractgates.- No
sync-plugin-version.yml(the discarded sync mechanism is not shipped in scaffolds; goreleaser'sbefore:hook rewritesplugin.json.versionfrom the tag at release time). sdk.WithBuildVersion(sdk.ResolveBuildVersion(internal.Version))wired in main.go so the binary surfaces its release version throughGetManifestat runtime.setup-wfctl@v1 with version: v0.62.0pinned for the release pipeline.
go build ./...
go test ./... -race -count=1git tag v0.1.0 && git push origin v0.1.0release.yml runs wfctl plugin validate-contract --for-publish,
goreleaser builds cross-platform binaries, and the post-build gate
verifies the shipped tarball's plugin.json carries the tag.
- Plugin release contract: docs/PLUGIN_RELEASE_GATES.md
- Plugin version discipline: workflow#758
- Registry sync subcommand: workflow#762