Skip to content

wfctl v0.50.1 still dispatches IaCProvider via legacy InvokeService — incompatible with strict-cutover plugins (DO v1.0.0) #622

@intel352

Description

@intel352

Summary

wfctl v0.50.1's `remoteIaCProvider` (cmd/wfctl/deploy_providers.go) dispatches every IaCProvider call (Name, Version, Initialize, Diff, Apply, Refresh, etc.) through the legacy `PluginService.InvokeService` gRPC method. DO plugin v1.0.0 (the first strict-cutover release; bumped workflow dep v0.27.1 → v0.50.0 + switched to `sdk.ServeIaCPlugin`) deletes `PluginService` entirely per the cutover plan. Result: every plan/apply against v1.0.0 plugin dies with:

```
error: rpc error: code = Unimplemented desc = unknown service workflow.plugin.v1.PluginService
```

Reproduction

BMW deploy run 25637844162 on sha 93ff871c (BMW PR #269 = DO plugin pin v0.14.3 → v1.0.0). `Plan staging infra` step:

```
[external-plugins] starting plugin "digitalocean" (version v1.0.0)
[external-plugins] plugin "digitalocean" loaded successfully
[external-plugins] shutting down plugin "digitalocean"
error: rpc error: code = Unimplemented desc = unknown service workflow.plugin.v1.PluginService
```

wfctl: v0.50.1. Plugin: v1.0.0.

Code path

`cmd/wfctl/deploy_providers.go`:

```go
// Line 251
InvokeService(method string, args map[string]any) (map[string]any, error)
// Line 255
InvokeServiceContext(ctx context.Context, method string, args map[string]any) (map[string]any, error)
```

All 9+ IaCProvider method shims (Name, Version, Initialize, ListResources, Plan, Apply, Refresh, …) call `r.invoker.InvokeService("IaCProvider.", …)`. This routes via the legacy `PluginService` gRPC service that DO v1.0.0 (and any strict-cutover plugin) no longer exposes.

PR #618 (typed-RPC capability discovery at 5 dispatch sites) added typed-RPC capability discovery but didn't switch the actual IaCProvider dispatch path away from InvokeService. The cutover is incomplete.

Recommendation

Either:

A. Finish the cutover: `remoteIaCProvider` switches to typed `pb.IaCProviderClient` (and per-driver `pb.ResourceDriverClient`) for all IaCProvider/ResourceDriver methods. Strict-cutover plugins work; legacy plugins break (per the "force-cutover, no compat" mandate).

B. Re-add a typed→legacy adapter on the plugin side so v1.0.0 retains `InvokeService` while also exposing typed servers, until wfctl finishes its side. Contradicts the cutover plan but unblocks consumers.

(A) is consistent with the documented mandate. Filing this so wfctl side can sequence the dispatch-path migration.

Blast radius

Every consumer pinning wfctl v0.27.7+ AND DO plugin v1.0.0+ is blocked. Today that's just BMW. Soon: any consumer that picks up DO plugin v1.0.0 (which closed #91 so consumers will be pulled toward it).

No working wfctl+DO pin pair exists right now:

  • wfctl ≤v0.27.6 + DO ≤v0.14.3 — works for non-eventbus configs, but no PR fix(wfctl): disambiguate iac_provider from impl-level provider in resource configs #620 iac_provider disambiguation; BMW eventbus configs trip plan-grouping.
  • wfctl v0.27.7..v0.50.1 + DO ≤v0.14.3 — DO plugin's v0.27.1 workflow dep predates strict-cutover; wfctl rejects with "plugin does not register the required IaCProviderRequired gRPC service".
  • wfctl v0.27.7..v0.50.1 + DO v1.0.0 — this issue.

Related

🤖 Filed by Claude Code on behalf of BMW deploy debug chain

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions