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
7 changes: 2 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ jobs:
go-version-file: go.mod
- uses: GoCodeAlone/setup-wfctl@v1
with:
version: v0.62.0
# workflow#762: scaffold carries type="scaffold" + TEMPLATE.* placeholders.
# Old `plugin validate --strict-contracts` (wfctl v0.20.1) rejects both;
# validate-contract (v0.62.0) checks scaffold-compatible contract surface.
- name: Validate plugin contract (scaffold-aware)
version: v0.63.1
- name: Validate plugin contract
run: wfctl plugin validate-contract .
10 changes: 4 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ jobs:
run: |
RUNNER_ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
BIN=$(jq -r --arg arch "$RUNNER_ARCH" \
'[.[] | select(.type=="Binary" and .goos=="linux" and .goarch==$arch and (.name|startswith("scaffold-workflow-plugin")))] | .[0].path // ""' \
'[.[] | select(.type=="Binary" and .goos=="linux" and .goarch==$arch and (.name|startswith("workflow-plugin-volunteer-science")))] | .[0].path // ""' \
dist/artifacts.json)
if [ -z "$BIN" ] || [ "$BIN" = "null" ]; then
echo "::warning::No matching linux/$RUNNER_ARCH scaffold binary in dist/artifacts.json; skipping verify-capabilities"
echo "::warning::No matching linux/$RUNNER_ARCH workflow-plugin-volunteer-science binary in dist/artifacts.json; skipping verify-capabilities"
jq '.[] | {name, type, goos, goarch, path}' dist/artifacts.json
exit 0
fi
Expand All @@ -56,7 +56,5 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release edit "${{ github.ref_name }}" --draft=false --repo "${{ github.repository }}"

# NOTE: scaffold-workflow-plugin does NOT notify workflow-registry on release
# — it's a scaffold repo, NOT an installable plugin. The notify-workflow-registry
# job is intentionally omitted (and registry-side type-allowlist defense
# in wfctl plugin registry-sync rejects type:"scaffold" if it ever leaks in).
# Registry publication is intentionally separate from binary release until
# workflow-compute consumes provider catalog plugins from the registry.
63 changes: 0 additions & 63 deletions .github/workflows/scaffold-rename-test.yml

This file was deleted.

8 changes: 4 additions & 4 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ before:
- "sed -i.bak 's/\"version\": \".*\"/\"version\": \"{{ .Version }}\"/' plugin.json && rm -f plugin.json.bak"

builds:
- id: scaffold-workflow-plugin
main: ./cmd/scaffold-workflow-plugin
binary: scaffold-workflow-plugin
- id: workflow-plugin-volunteer-science
main: ./cmd/workflow-plugin-volunteer-science
binary: workflow-plugin-volunteer-science
env:
- CGO_ENABLED=0
goos:
Expand All @@ -19,7 +19,7 @@ builds:
- amd64
- arm64
ldflags:
- -s -w -X main.version={{.Version}} -X github.com/GoCodeAlone/scaffold-workflow-plugin/internal.Version={{.Version}}
- -s -w -X main.version={{.Version}} -X github.com/GoCodeAlone/workflow-plugin-volunteer-science/internal.Version={{.Version}}

archives:
- formats: [tar.gz]
Expand Down
46 changes: 13 additions & 33 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# CLAUDE.md — Workflow Plugin Template
# CLAUDE.md — workflow-plugin-volunteer-science

External gRPC plugin for the GoCodeAlone/workflow engine.
External gRPC plugin for volunteer science provider catalog metadata consumed
by Workflow and `workflow-compute`.

## Build & Test

Expand All @@ -9,40 +10,19 @@ go build ./...
go test ./... -v -race -count=1
```

## Cross-compile for deployment
## Cross-compile

```sh
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -ldflags="-s -w" -o scaffold-workflow-plugin ./cmd/scaffold-workflow-plugin/
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -ldflags="-s -w" -o workflow-plugin-volunteer-science ./cmd/workflow-plugin-volunteer-science/
```

## Structure

- `cmd/scaffold-workflow-plugin/main.go` — Plugin entry point (calls `sdk.Serve`)
- `internal/plugin.go` — Plugin manifest, module factories, step factories
- `internal/` — All module and step implementations
- `plugin.json` — Capability manifest for the workflow registry
- `.goreleaser.yaml` — GoReleaser v2 config for cross-platform releases
- `.github/workflows/ci.yml` — CI on push/PR (build + test)
- `.github/workflows/release.yml` — Release on v* tag push (GoReleaser)

## Adding a Module Type

1. Create `internal/module_example.go` implementing the module
2. Register in `internal/plugin.go` ModuleFactories()
3. Add to `plugin.json` capabilities.moduleTypes
4. Add tests in `internal/module_example_test.go`

## Adding a Step Type

1. Create `internal/step_example.go` implementing the step
2. Register in `internal/plugin.go` StepFactories()
3. Add to `plugin.json` capabilities.stepTypes
4. Add tests in `internal/step_example_test.go`

## Releasing

```sh
git tag v0.1.0
git push origin v0.1.0
```
GoReleaser builds cross-platform binaries and creates a GitHub Release automatically.
- `cmd/workflow-plugin-volunteer-science/main.go` — external plugin entrypoint
- `internal/plugin.go` — Workflow plugin manifest
- `catalog/folding.go` — public Folding@home provider catalog metadata
- `catalog/types.go` — public JSON-compatible provider catalog types
- `plugin.json` — registry-facing plugin manifest
- `.goreleaser.yaml` — GoReleaser v2 config for releases
- `.github/workflows/ci.yml` — build, test, vet, and plugin contract validation
- `.github/workflows/release.yml` — tagged release pipeline
110 changes: 18 additions & 92 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,103 +1,29 @@
# scaffold-workflow-plugin
# workflow-plugin-volunteer-science

This is a SCAFFOLD repo. It is NOT an installable plugin.
Public Workflow plugin for volunteer science provider catalog metadata used by
`workflow-compute`. The catalog package intentionally avoids private module
dependencies so this public plugin can build on public CI and be imported by
future public tooling.

Use it to create a new workflow plugin via GitHub's "Use this template" button.
The plugin currently owns shape-only upstream-client requirements for
Folding@home. Real-client promotion requires digest-pinned FAHClient images and
stored version evidence before provider contracts can claim real upstream
conformance.

(A future `wfctl plugin init --from-scaffold` subcommand is tracked at
[workflow#762](https://github.com/GoCodeAlone/workflow/issues/762) but
not yet implemented; use the GitHub UI path below.)
## Build & Test

## After creating your new repo from this template

1. **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.

2. **Run the rename script**:

```bash
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.mod` module path.
- Bulk-sed of `scaffold-workflow-plugin` → `workflow-plugin-<your-name>`
across `.go`/`.yaml`/`.md`/`plugin.json` files.
- Resets `plugin.json.type` from `"scaffold"` to `"external"`; sets `.name`.
- Removes the rename script itself + scaffold-rename-test workflow.

3. **Edit `plugin.json`**: replace `TEMPLATE.module` / `TEMPLATE.step` /
`TEMPLATE.resource` placeholder capabilities with your plugin's actual
types. Update `minEngineVersion` if you depend on a newer workflow.

4. **Implement your plugin** in `internal/`:
- **non-IaC mode**: extend `internal/plugin.go`'s `NewPlugin()` with
real ModuleFactories / StepFactories / TriggerFactories. Delete
`internal/iacserver.go` (unused in non-IaC mode).
- **IaC mode**: replace `internal/iacserver.go`'s stub
`pb.UnimplementedIaCProviderRequiredServer` embed with your real
IaC provider implementation (Initialize, Plan, Destroy, etc.).
Delete `internal/plugin.go`'s NewPlugin (unused in IaC mode).

5. **Commit + tag**:

```bash
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`'s `wfctl plugin validate-contract --for-publish` gate
verifies your tag (must be release-grade semver `^v\d+\.\d+\.\d+$`)
and contract (capabilities populated, minEngineVersion set, main.go
wires `sdk.ResolveBuildVersion`, goreleaser ldflag present).

## Modes

- `--mode non-iac` (default): for module/step/trigger plugins that use
`sdk.Serve`. Suitable for MOST plugins.
- `--mode iac`: for IaC provider plugins that use `sdk.ServeIaCPlugin`
and satisfy `pb.IaCProviderRequiredServer`. Use ONLY if your plugin
provisions infrastructure (cloud resources, databases, etc.).

## What's pre-baked in (workflow#758 + #762 compliance)

- `plugin.json.version = "0.0.0"` sentinel (release tag injected at build
time via goreleaser).
- `internal/plugin.go`'s `var Version = "0.0.0"` (ldflag-injected at
release; surfaced through `sdk.ResolveBuildVersion`).
- `release.yml` pre-build + post-build `wfctl plugin validate-contract`
gates.
- No `sync-plugin-version.yml` (the discarded sync mechanism is not
shipped in scaffolds; goreleaser's `before:` hook rewrites
`plugin.json.version` from the tag at release time).
- `sdk.WithBuildVersion(sdk.ResolveBuildVersion(internal.Version))`
wired in main.go so the binary surfaces its release version through
`GetManifest` at runtime.
- `setup-wfctl@v1 with version: v0.62.0` pinned for the release pipeline.

## Build & test (during plugin development)

```bash
```sh
go build ./...
go test ./... -race -count=1
```

## Releasing
## Release

```bash
git tag v0.1.0 && git push origin v0.1.0
```sh
git tag v0.1.0
git push origin v0.1.0
```

`release.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.

## References

- Plugin release contract: [docs/PLUGIN_RELEASE_GATES.md](https://github.com/GoCodeAlone/workflow/blob/main/docs/PLUGIN_RELEASE_GATES.md)
- Plugin version discipline: [workflow#758](https://github.com/GoCodeAlone/workflow/issues/758)
- Registry sync subcommand: [workflow#762](https://github.com/GoCodeAlone/workflow/issues/762)
The release workflow validates `plugin.json`, builds cross-platform binaries
with GoReleaser, and verifies the runtime plugin manifest against the shipped
contract metadata.
37 changes: 37 additions & 0 deletions catalog/folding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package catalog

const volunteerSciencePluginID = "workflow-plugin-volunteer-science"

func FoldingUpstreamClientRequirement() ProviderUpstreamClientRequirement {
runtime := DefaultProviderRuntimeProfile("service-sandboxed-container", ExecutionSandboxedContainer, ProofArtifactHash)
return ProviderUpstreamClientRequirement{
ProtocolVersion: Version,
PluginID: volunteerSciencePluginID,
ProviderID: "folding-at-home",
ContractID: "folding-at-home.client.v1",
Version: "v1.0.0",
RuntimeProfileID: runtime.ID,
ConformanceProfile: "upstream-client-v1",
DefaultConformance: UpstreamClientConformanceShapeOnly,
RealClientConformance: UpstreamClientConformanceRealClient,
UpstreamClientName: "FAHClient",
VersionProbeCommand: []string{"FAHClient", "--version"},
ImagePolicy: ProviderUpstreamImagePolicy{
DigestPinnedImageRequired: true,
RecommendedImageRef: "foldingathome/fah-gpu@sha256:<digest>",
KnownImageRefs: []string{
"foldingathome/fah-gpu@sha256:<digest>",
"foldingathome/fah-gpu-amd@sha256:<digest>",
},
},
RequiredEvidence: []string{
"digest-pinned OCI image reference",
"artifact:// provider conformance evidence with sha256 digest",
"upstream-client-v1 version probe artifact",
},
Notes: []string{
"Folding@home real-client promotion requires a digest-pinned FAHClient image and stored version evidence",
"shape-only remains the default until real upstream-client-v1 evidence is attached to the provider contract",
},
}
}
20 changes: 20 additions & 0 deletions catalog/protocol_aliases.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package catalog

import core "github.com/GoCodeAlone/workflow-plugin-compute-core/protocol"

const (
Version = core.Version

ExecutionSandboxedContainer = core.ExecutionSandboxedContainer
ProofArtifactHash = core.ProofArtifactHash

UpstreamClientConformanceShapeOnly = core.UpstreamClientConformanceShapeOnly
UpstreamClientConformanceRealClient = core.UpstreamClientConformanceRealClient
)

type (
ProviderUpstreamClientRequirement = core.ProviderUpstreamClientRequirement
ProviderUpstreamImagePolicy = core.ProviderUpstreamImagePolicy
)

var DefaultProviderRuntimeProfile = core.DefaultProviderRuntimeProfile
23 changes: 0 additions & 23 deletions cmd/scaffold-workflow-plugin-iac/main.go

This file was deleted.

Loading
Loading