Skip to content

fix(plugin/external/sdk): register PluginService bridge in RegisterAllIaCProviderServices so wfctl can call GetContractRegistry on strict-cutover IaC plugins#623

Merged
intel352 merged 3 commits into
mainfrom
copilot/fix-legacy-invokeservice-dispatch
May 10, 2026
Merged

fix(plugin/external/sdk): register PluginService bridge in RegisterAllIaCProviderServices so wfctl can call GetContractRegistry on strict-cutover IaC plugins#623
intel352 merged 3 commits into
mainfrom
copilot/fix-legacy-invokeservice-dispatch

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 10, 2026

ServeIaCPlugin (the SDK entrypoint for DO v1.0.0-style plugins) calls RegisterAllIaCProviderServices, which only registered typed IaC gRPC services. wfctl's NewExternalPluginAdapter always calls GetContractRegistry via pb.NewPluginServiceClient to discover optional capabilities — but PluginService was never registered, so every load attempt died with:

unknown service workflow.plugin.v1.PluginService

This blocked buildTypedIaCAdapterFrom before it could even check for IaCProviderRequired, making the fully-typed dispatch path unreachable for any strict-cutover plugin.

Changes

  • plugin/external/sdk/iacserver.go — add iacPluginServiceBridge, a minimal pb.PluginServiceServer that implements only GetContractRegistry by delegating to BuildContractRegistry(s), which enumerates the gRPC services already registered on the server. RegisterAllIaCProviderServices registers the bridge at the end, guarded against double-registration for mixed plugins that also call sdk.Serve.

  • plugin/external/sdk/iacserver_test.go — three new tests:

    • …_PluginServiceBridgeRegistered: verifies workflow.plugin.v1.PluginService appears in GetServiceInfo() after registration
    • …_PluginServiceBridgeAnswersGetContractRegistry: end-to-end via a live in-process gRPC client — confirms GetContractRegistry returns IaCProviderRequired in the registry (the exact check buildTypedIaCAdapterFrom performs)
    • …_PluginServiceAlreadyRegistered_NoPanic: verifies the double-registration guard on mixed-plugin servers

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 10, 2026

⏱ Benchmark Results

No significant performance regressions detected.

benchstat comparison (baseline → PR)
## benchstat: baseline → PR
baseline-bench.txt:262: parsing iteration count: invalid syntax
baseline-bench.txt:328520: parsing iteration count: invalid syntax
baseline-bench.txt:631446: parsing iteration count: invalid syntax
baseline-bench.txt:1120261: parsing iteration count: invalid syntax
baseline-bench.txt:1430399: parsing iteration count: invalid syntax
baseline-bench.txt:1746477: parsing iteration count: invalid syntax
benchmark-results.txt:262: parsing iteration count: invalid syntax
benchmark-results.txt:351674: parsing iteration count: invalid syntax
benchmark-results.txt:680871: parsing iteration count: invalid syntax
benchmark-results.txt:1025656: parsing iteration count: invalid syntax
benchmark-results.txt:1373354: parsing iteration count: invalid syntax
benchmark-results.txt:1741545: parsing iteration count: invalid syntax
goos: linux
goarch: amd64
pkg: github.com/GoCodeAlone/workflow/dynamic
cpu: AMD EPYC 9V74 80-Core Processor                
                            │ baseline-bench.txt │
                            │       sec/op       │
InterpreterCreation-4              3.293m ± 174%
ComponentLoad-4                    3.489m ±   0%
ComponentExecute-4                 1.841µ ±   6%
PoolContention/workers-1-4         1.022µ ±   3%
PoolContention/workers-2-4         1.020µ ±   1%
PoolContention/workers-4-4         1.022µ ±   1%
PoolContention/workers-8-4         1.019µ ±   4%
PoolContention/workers-16-4        1.016µ ±   1%
ComponentLifecycle-4               3.512m ±   1%
SourceValidation-4                 2.113µ ±   2%
RegistryConcurrent-4               766.4n ±   3%
LoaderLoadFromString-4             3.603m ±   0%
geomean                            16.72µ

                            │ baseline-bench.txt │
                            │        B/op        │
InterpreterCreation-4               2.027Mi ± 0%
ComponentLoad-4                     2.180Mi ± 0%
ComponentExecute-4                  1.203Ki ± 0%
PoolContention/workers-1-4          1.203Ki ± 0%
PoolContention/workers-2-4          1.203Ki ± 0%
PoolContention/workers-4-4          1.203Ki ± 0%
PoolContention/workers-8-4          1.203Ki ± 0%
PoolContention/workers-16-4         1.203Ki ± 0%
ComponentLifecycle-4                2.183Mi ± 0%
SourceValidation-4                  1.984Ki ± 0%
RegistryConcurrent-4                1.133Ki ± 0%
LoaderLoadFromString-4              2.182Mi ± 0%
geomean                             15.25Ki

                            │ baseline-bench.txt │
                            │     allocs/op      │
InterpreterCreation-4                15.68k ± 0%
ComponentLoad-4                      18.02k ± 0%
ComponentExecute-4                    25.00 ± 0%
PoolContention/workers-1-4            25.00 ± 0%
PoolContention/workers-2-4            25.00 ± 0%
PoolContention/workers-4-4            25.00 ± 0%
PoolContention/workers-8-4            25.00 ± 0%
PoolContention/workers-16-4           25.00 ± 0%
ComponentLifecycle-4                 18.07k ± 0%
SourceValidation-4                    32.00 ± 0%
RegistryConcurrent-4                  2.000 ± 0%
LoaderLoadFromString-4               18.06k ± 0%
geomean                               183.3

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                            │ benchmark-results.txt │
                            │        sec/op         │
InterpreterCreation-4                 3.065m ± 212%
ComponentLoad-4                       3.475m ±   9%
ComponentExecute-4                    1.854µ ±   1%
PoolContention/workers-1-4            1.195µ ±   1%
PoolContention/workers-2-4            1.190µ ±   1%
PoolContention/workers-4-4            1.194µ ±   1%
PoolContention/workers-8-4            1.200µ ±   1%
PoolContention/workers-16-4           1.218µ ±   1%
ComponentLifecycle-4                  3.567m ±   1%
SourceValidation-4                    2.230µ ±   1%
RegistryConcurrent-4                  891.2n ±   2%
LoaderLoadFromString-4                3.655m ±   2%
geomean                               18.14µ

                            │ benchmark-results.txt │
                            │         B/op          │
InterpreterCreation-4                  2.027Mi ± 0%
ComponentLoad-4                        2.180Mi ± 0%
ComponentExecute-4                     1.203Ki ± 0%
PoolContention/workers-1-4             1.203Ki ± 0%
PoolContention/workers-2-4             1.203Ki ± 0%
PoolContention/workers-4-4             1.203Ki ± 0%
PoolContention/workers-8-4             1.203Ki ± 0%
PoolContention/workers-16-4            1.203Ki ± 0%
ComponentLifecycle-4                   2.183Mi ± 0%
SourceValidation-4                     1.984Ki ± 0%
RegistryConcurrent-4                   1.133Ki ± 0%
LoaderLoadFromString-4                 2.182Mi ± 0%
geomean                                15.25Ki

                            │ benchmark-results.txt │
                            │       allocs/op       │
InterpreterCreation-4                   15.68k ± 0%
ComponentLoad-4                         18.02k ± 0%
ComponentExecute-4                       25.00 ± 0%
PoolContention/workers-1-4               25.00 ± 0%
PoolContention/workers-2-4               25.00 ± 0%
PoolContention/workers-4-4               25.00 ± 0%
PoolContention/workers-8-4               25.00 ± 0%
PoolContention/workers-16-4              25.00 ± 0%
ComponentLifecycle-4                    18.07k ± 0%
SourceValidation-4                       32.00 ± 0%
RegistryConcurrent-4                     2.000 ± 0%
LoaderLoadFromString-4                  18.06k ± 0%
geomean                                  183.3

pkg: github.com/GoCodeAlone/workflow/middleware
cpu: AMD EPYC 9V74 80-Core Processor                
                                  │ baseline-bench.txt │
                                  │       sec/op       │
CircuitBreakerDetection-4                  298.7n ± 3%
CircuitBreakerExecution_Success-4          22.68n ± 1%
CircuitBreakerExecution_Failure-4          71.16n ± 0%
geomean                                    78.41n

                                  │ baseline-bench.txt │
                                  │        B/op        │
CircuitBreakerDetection-4                 144.0 ± 0%
CircuitBreakerExecution_Success-4         0.000 ± 0%
CircuitBreakerExecution_Failure-4         0.000 ± 0%
geomean                                              ¹
¹ summaries must be >0 to compute geomean

                                  │ baseline-bench.txt │
                                  │     allocs/op      │
CircuitBreakerDetection-4                 1.000 ± 0%
CircuitBreakerExecution_Success-4         0.000 ± 0%
CircuitBreakerExecution_Failure-4         0.000 ± 0%
geomean                                              ¹
¹ summaries must be >0 to compute geomean

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                  │ benchmark-results.txt │
                                  │        sec/op         │
CircuitBreakerDetection-4                    455.6n ±  3%
CircuitBreakerExecution_Success-4            59.70n ±  0%
CircuitBreakerExecution_Failure-4            66.51n ± 12%
geomean                                      121.8n

                                  │ benchmark-results.txt │
                                  │         B/op          │
CircuitBreakerDetection-4                    144.0 ± 0%
CircuitBreakerExecution_Success-4            0.000 ± 0%
CircuitBreakerExecution_Failure-4            0.000 ± 0%
geomean                                                 ¹
¹ summaries must be >0 to compute geomean

                                  │ benchmark-results.txt │
                                  │       allocs/op       │
CircuitBreakerDetection-4                    1.000 ± 0%
CircuitBreakerExecution_Success-4            0.000 ± 0%
CircuitBreakerExecution_Failure-4            0.000 ± 0%
geomean                                                 ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/module
cpu: AMD EPYC 9V74 80-Core Processor                
                                 │ baseline-bench.txt │
                                 │       sec/op       │
JQTransform_Simple-4                     845.4n ± 31%
JQTransform_ObjectConstruction-4         1.414µ ±  1%
JQTransform_ArraySelect-4                3.557µ ±  0%
JQTransform_Complex-4                    43.15µ ±  1%
JQTransform_Throughput-4                 1.739µ ±  2%
SSEPublishDelivery-4                     62.84n ±  1%
geomean                                  1.648µ

                                 │ baseline-bench.txt │
                                 │        B/op        │
JQTransform_Simple-4                   1.273Ki ± 0%
JQTransform_ObjectConstruction-4       1.773Ki ± 0%
JQTransform_ArraySelect-4              2.625Ki ± 0%
JQTransform_Complex-4                  16.22Ki ± 0%
JQTransform_Throughput-4               1.984Ki ± 0%
SSEPublishDelivery-4                     0.000 ± 0%
geomean                                             ¹
¹ summaries must be >0 to compute geomean

                                 │ baseline-bench.txt │
                                 │     allocs/op      │
JQTransform_Simple-4                     10.00 ± 0%
JQTransform_ObjectConstruction-4         15.00 ± 0%
JQTransform_ArraySelect-4                30.00 ± 0%
JQTransform_Complex-4                    324.0 ± 0%
JQTransform_Throughput-4                 17.00 ± 0%
SSEPublishDelivery-4                     0.000 ± 0%
geomean                                             ¹
¹ summaries must be >0 to compute geomean

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                 │ benchmark-results.txt │
                                 │        sec/op         │
JQTransform_Simple-4                        893.2n ± 27%
JQTransform_ObjectConstruction-4            1.476µ ± 25%
JQTransform_ArraySelect-4                   3.138µ ±  1%
JQTransform_Complex-4                       34.87µ ±  2%
JQTransform_Throughput-4                    1.773µ ±  0%
SSEPublishDelivery-4                        76.92n ±  3%
geomean                                     1.643µ

                                 │ benchmark-results.txt │
                                 │         B/op          │
JQTransform_Simple-4                      1.273Ki ± 0%
JQTransform_ObjectConstruction-4          1.773Ki ± 0%
JQTransform_ArraySelect-4                 2.625Ki ± 0%
JQTransform_Complex-4                     16.22Ki ± 0%
JQTransform_Throughput-4                  1.984Ki ± 0%
SSEPublishDelivery-4                        0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

                                 │ benchmark-results.txt │
                                 │       allocs/op       │
JQTransform_Simple-4                        10.00 ± 0%
JQTransform_ObjectConstruction-4            15.00 ± 0%
JQTransform_ArraySelect-4                   30.00 ± 0%
JQTransform_Complex-4                       324.0 ± 0%
JQTransform_Throughput-4                    17.00 ± 0%
SSEPublishDelivery-4                        0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/schema
cpu: AMD EPYC 9V74 80-Core Processor                
                                    │ baseline-bench.txt │
                                    │       sec/op       │
SchemaValidation_Simple-4                   1.089µ ± 20%
SchemaValidation_AllFields-4                1.636µ ±  6%
SchemaValidation_FormatValidation-4         1.572µ ±  1%
SchemaValidation_ManySchemas-4              1.591µ ±  3%
geomean                                     1.453µ

                                    │ baseline-bench.txt │
                                    │        B/op        │
SchemaValidation_Simple-4                   0.000 ± 0%
SchemaValidation_AllFields-4                0.000 ± 0%
SchemaValidation_FormatValidation-4         0.000 ± 0%
SchemaValidation_ManySchemas-4              0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

                                    │ baseline-bench.txt │
                                    │     allocs/op      │
SchemaValidation_Simple-4                   0.000 ± 0%
SchemaValidation_AllFields-4                0.000 ± 0%
SchemaValidation_FormatValidation-4         0.000 ± 0%
SchemaValidation_ManySchemas-4              0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                    │ benchmark-results.txt │
                                    │        sec/op         │
SchemaValidation_Simple-4                       1.035µ ± 6%
SchemaValidation_AllFields-4                    1.533µ ± 2%
SchemaValidation_FormatValidation-4             1.503µ ± 1%
SchemaValidation_ManySchemas-4                  1.484µ ± 1%
geomean                                         1.372µ

                                    │ benchmark-results.txt │
                                    │         B/op          │
SchemaValidation_Simple-4                      0.000 ± 0%
SchemaValidation_AllFields-4                   0.000 ± 0%
SchemaValidation_FormatValidation-4            0.000 ± 0%
SchemaValidation_ManySchemas-4                 0.000 ± 0%
geomean                                                   ¹
¹ summaries must be >0 to compute geomean

                                    │ benchmark-results.txt │
                                    │       allocs/op       │
SchemaValidation_Simple-4                      0.000 ± 0%
SchemaValidation_AllFields-4                   0.000 ± 0%
SchemaValidation_FormatValidation-4            0.000 ± 0%
SchemaValidation_ManySchemas-4                 0.000 ± 0%
geomean                                                   ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/store
cpu: AMD EPYC 9V74 80-Core Processor                
                                   │ baseline-bench.txt │
                                   │       sec/op       │
EventStoreAppend_InMemory-4                1.157µ ± 12%
EventStoreAppend_SQLite-4                  1.063m ± 10%
GetTimeline_InMemory/events-10-4           12.74µ ±  3%
GetTimeline_InMemory/events-50-4           70.24µ ±  2%
GetTimeline_InMemory/events-100-4          117.5µ ± 20%
GetTimeline_InMemory/events-500-4          559.1µ ±  1%
GetTimeline_InMemory/events-1000-4         1.136m ±  1%
GetTimeline_SQLite/events-10-4             84.89µ ±  6%
GetTimeline_SQLite/events-50-4             219.6µ ±  1%
GetTimeline_SQLite/events-100-4            384.3µ ±  1%
GetTimeline_SQLite/events-500-4            1.663m ±  1%
GetTimeline_SQLite/events-1000-4           3.238m ±  1%
geomean                                    195.8µ

                                   │ baseline-bench.txt │
                                   │        B/op        │
EventStoreAppend_InMemory-4                  754.5 ± 7%
EventStoreAppend_SQLite-4                  1.983Ki ± 2%
GetTimeline_InMemory/events-10-4           7.953Ki ± 0%
GetTimeline_InMemory/events-50-4           46.62Ki ± 0%
GetTimeline_InMemory/events-100-4          94.48Ki ± 0%
GetTimeline_InMemory/events-500-4          472.8Ki ± 0%
GetTimeline_InMemory/events-1000-4         944.3Ki ± 0%
GetTimeline_SQLite/events-10-4             16.74Ki ± 0%
GetTimeline_SQLite/events-50-4             87.14Ki ± 0%
GetTimeline_SQLite/events-100-4            175.4Ki ± 0%
GetTimeline_SQLite/events-500-4            846.1Ki ± 0%
GetTimeline_SQLite/events-1000-4           1.639Mi ± 0%
geomean                                    67.08Ki

                                   │ baseline-bench.txt │
                                   │     allocs/op      │
EventStoreAppend_InMemory-4                  7.000 ± 0%
EventStoreAppend_SQLite-4                    53.00 ± 0%
GetTimeline_InMemory/events-10-4             125.0 ± 0%
GetTimeline_InMemory/events-50-4             653.0 ± 0%
GetTimeline_InMemory/events-100-4           1.306k ± 0%
GetTimeline_InMemory/events-500-4           6.514k ± 0%
GetTimeline_InMemory/events-1000-4          13.02k ± 0%
GetTimeline_SQLite/events-10-4               382.0 ± 0%
GetTimeline_SQLite/events-50-4              1.852k ± 0%
GetTimeline_SQLite/events-100-4             3.681k ± 0%
GetTimeline_SQLite/events-500-4             18.54k ± 0%
GetTimeline_SQLite/events-1000-4            37.29k ± 0%
geomean                                     1.162k

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                   │ benchmark-results.txt │
                                   │        sec/op         │
EventStoreAppend_InMemory-4                   1.132µ ± 10%
EventStoreAppend_SQLite-4                     977.8µ ±  2%
GetTimeline_InMemory/events-10-4              13.43µ ±  3%
GetTimeline_InMemory/events-50-4              75.01µ ±  2%
GetTimeline_InMemory/events-100-4             135.7µ ± 14%
GetTimeline_InMemory/events-500-4             604.2µ ±  1%
GetTimeline_InMemory/events-1000-4            1.227m ±  0%
GetTimeline_SQLite/events-10-4                81.51µ ±  1%
GetTimeline_SQLite/events-50-4                233.9µ ±  1%
GetTimeline_SQLite/events-100-4               419.6µ ±  2%
GetTimeline_SQLite/events-500-4               1.889m ±  0%
GetTimeline_SQLite/events-1000-4              3.710m ±  1%
geomean                                       207.3µ

                                   │ benchmark-results.txt │
                                   │         B/op          │
EventStoreAppend_InMemory-4                    835.5 ± 11%
EventStoreAppend_SQLite-4                    1.983Ki ±  1%
GetTimeline_InMemory/events-10-4             7.953Ki ±  0%
GetTimeline_InMemory/events-50-4             46.62Ki ±  0%
GetTimeline_InMemory/events-100-4            94.48Ki ±  0%
GetTimeline_InMemory/events-500-4            472.8Ki ±  0%
GetTimeline_InMemory/events-1000-4           944.3Ki ±  0%
GetTimeline_SQLite/events-10-4               16.74Ki ±  0%
GetTimeline_SQLite/events-50-4               87.14Ki ±  0%
GetTimeline_SQLite/events-100-4              175.4Ki ±  0%
GetTimeline_SQLite/events-500-4              846.1Ki ±  0%
GetTimeline_SQLite/events-1000-4             1.639Mi ±  0%
geomean                                      67.66Ki

                                   │ benchmark-results.txt │
                                   │       allocs/op       │
EventStoreAppend_InMemory-4                     7.000 ± 0%
EventStoreAppend_SQLite-4                       53.00 ± 0%
GetTimeline_InMemory/events-10-4                125.0 ± 0%
GetTimeline_InMemory/events-50-4                653.0 ± 0%
GetTimeline_InMemory/events-100-4              1.306k ± 0%
GetTimeline_InMemory/events-500-4              6.514k ± 0%
GetTimeline_InMemory/events-1000-4             13.02k ± 0%
GetTimeline_SQLite/events-10-4                  382.0 ± 0%
GetTimeline_SQLite/events-50-4                 1.852k ± 0%
GetTimeline_SQLite/events-100-4                3.681k ± 0%
GetTimeline_SQLite/events-500-4                18.54k ± 0%
GetTimeline_SQLite/events-1000-4               37.29k ± 0%
geomean                                        1.162k

Benchmarks run with go test -bench=. -benchmem -count=6.
Regressions ≥ 20% are flagged. Results compared via benchstat.

…lIaCProviderServices for GetContractRegistry support

ServeIaCPlugin (used by DO plugin v1.0.0) calls RegisterAllIaCProviderServices
which only registered typed IaC gRPC services. When wfctl's
NewExternalPluginAdapter called GetContractRegistry via pb.NewPluginServiceClient,
the plugin returned 'unknown service workflow.plugin.v1.PluginService',
blocking the typedIaCAdapter load path in buildTypedIaCAdapterFrom.

Fix: after registering IaC services, also register a minimal
iacPluginServiceBridge as PluginServiceServer. The bridge's
GetContractRegistry delegates to BuildContractRegistry(s) which enumerates
all registered gRPC services on the server, returning the IaC service
descriptors wfctl needs for optional-client construction. A guard prevents
double-registration on mixed plugins that also run the SDK grpcServer.

Tests:
- TestRegisterAllIaCProviderServices_PluginServiceBridgeRegistered
- TestRegisterAllIaCProviderServices_PluginServiceBridgeAnswersGetContractRegistry
  (end-to-end via live in-process gRPC client)
- TestRegisterAllIaCProviderServices_PluginServiceAlreadyRegistered_NoPanic

Agent-Logs-Url: https://github.com/GoCodeAlone/workflow/sessions/8995eb0b-2f92-48fc-ac39-7b3b9a8a4c00

Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot May 10, 2026 20:38
Copilot AI changed the title [WIP] Fix wfctl v0.50.1 dispatch of IaCProvider through legacy InvokeService fix(plugin/external/sdk): register PluginService bridge in RegisterAllIaCProviderServices so wfctl can call GetContractRegistry on strict-cutover IaC plugins May 10, 2026
Copilot AI requested a review from intel352 May 10, 2026 20:40
@intel352 intel352 marked this pull request as ready for review May 10, 2026 21:50
Copilot AI review requested due to automatic review settings May 10, 2026 21:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes strict-cutover typed IaC plugins served via sdk.ServeIaCPlugin failing to load in wfctl because PluginService (specifically GetContractRegistry) was never registered on the plugin’s gRPC server.

Changes:

  • Register a minimal PluginService bridge from RegisterAllIaCProviderServices to serve GetContractRegistry for typed IaC-only plugins.
  • Implement iacPluginServiceBridge.GetContractRegistry by delegating to BuildContractRegistry(*grpc.Server).
  • Add tests validating the bridge is registered, responds end-to-end over gRPC, and does not double-register/panic on mixed-plugin servers.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
plugin/external/sdk/iacserver.go Registers a minimal PluginService bridge so wfctl can call GetContractRegistry on typed IaC plugins.
plugin/external/sdk/iacserver_test.go Adds coverage for bridge registration, RPC behavior, and double-registration guard.

Comment thread plugin/external/sdk/iacserver.go Outdated
Comment on lines +225 to +228
grpcSrv := grpc.NewServer()
// Pre-register PluginService (simulates a mixed sdk.Serve + IaC plugin).
pb.RegisterPluginServiceServer(grpcSrv, &pb.UnimplementedPluginServiceServer{})
// RegisterAllIaCProviderServices must not panic on double-registration.
@intel352
Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

…bedded-by-value stub

- Replace hard-coded "workflow.plugin.v1.PluginService" string in
  double-registration guard with pb.PluginService_ServiceDesc.ServiceName
  so drift/typos if the proto package name changes are caught at compile time.
- In the NoPanic test, replace &pb.UnimplementedPluginServiceServer{} with a
  local stub type that embeds UnimplementedPluginServiceServer by value,
  matching the pattern the generated gRPC code recommends.

Agent-Logs-Url: https://github.com/GoCodeAlone/workflow/sessions/460fbd7b-0c6c-46f0-b681-e364ed8a8889

Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 10, 2026

@copilot apply changes based on the comments in this thread

Done in 7204a16:

  • Double-registration guard now uses pb.PluginService_ServiceDesc.ServiceName instead of the hard-coded string.
  • The NoPanic test uses a local minimalPluginSvc stub that embeds UnimplementedPluginServiceServer by value, matching the pattern gRPC generated code recommends.

@intel352 intel352 merged commit 2ef2381 into main May 10, 2026
22 checks passed
@intel352 intel352 deleted the copilot/fix-legacy-invokeservice-dispatch branch May 10, 2026 22:22
intel352 added a commit that referenced this pull request May 10, 2026
…utover IaC plugins (#627)

NewExternalPluginAdapter currently fails outright when GetManifest returns
codes.Unimplemented. PR #623 added the iacPluginServiceBridge that wires
GetContractRegistry for strict-cutover IaC plugins (DO v1.0.0+), but the
bridge intentionally leaves GetManifest unimplemented (per the bridge's
inline comment). Loader-side adapter.go didn't get a matching relaxation,
so DO v1.0.1 loads its gRPC server, then immediately fails:

  rpc error: code = Unimplemented desc = method GetManifest not implemented
  load plugin "digitalocean": get manifest from plugin digitalocean

This blocks every consumer running typed-IaC dispatch against a
strict-cutover plugin. Observed end-to-end via core-dump
strict-contracts-smoke run 25642339926 against staging.

Fix: when GetManifest returns codes.Unimplemented, synthesize a minimal
Manifest{Name: name} from the param-passed plugin name. Downstream
accessors (Name/Version/Description/etc.) return sensible values; the
loader already keys off the param-passed name everywhere meaningful
(adapter.go:111). Non-Unimplemented errors still fail as before.

Tests:
- TestNewExternalPluginAdapter_GetManifestUnimplemented_SynthesizesFromName
- TestNewExternalPluginAdapter_GetManifestNonUnimplementedError_Fails

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

3 participants