Skip to content

fix(wfctl): isIaCNotFound — gRPC string fallback for adoption#734

Merged
intel352 merged 1 commit into
mainfrom
fix/iac-notfound-grpc-1779263168
May 20, 2026
Merged

fix(wfctl): isIaCNotFound — gRPC string fallback for adoption#734
intel352 merged 1 commit into
mainfrom
fix/iac-notfound-grpc-1779263168

Conversation

@intel352
Copy link
Copy Markdown
Contributor

Adoption falls back to create when driver.Read says not-found. For remote gRPC plugins the typed adapter loses sentinel identity, so errors.Is fails. Substring fallback restores the adoption path. 4 unit tests.

Adoption ("look up, fall back to create" for adopt_existing
resources) calls driver.Read and expects to skip on
ErrResourceNotFound. For remote gRPC-bridged plugins the typed
adapter loses sentinel identity across the wire — `errors.Is`
returns false even though the wrapped string is the canonical
ErrResourceNotFound.Error() ("iac: resource not found").

Result: workflow-plugin-digitalocean v2 database adoption fails
every apply with "rpc error: code = Unknown desc = database
\"multisite-pg\": iac: resource not found".

Add a substring fallback to isIaCNotFound that matches the
canonical sentinel message. Native typed-sentinel + platform-typed
paths still handled first. 4 tests cover all branches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 20, 2026 07:47
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

Improves wfctl infra apply adoption behavior by reliably treating certain remote-plugin Read() failures as “not found”, even when the gRPC boundary flattens the original sentinel error such that errors.Is no longer matches.

Changes:

  • Extend isIaCNotFound to fall back to substring matching on interfaces.ErrResourceNotFound.Error() after typed checks.
  • Add unit tests covering typed sentinel detection, gRPC-flattened string detection, nil safety, and non-matching errors.

Reviewed changes

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

File Description
cmd/wfctl/infra_apply.go Adds a string-based fallback to detect “resource not found” across gRPC-flattened errors so adoption can safely fall back to create.
cmd/wfctl/infra_apply_isiacnotfound_test.go Adds focused unit coverage for isIaCNotFound across sentinel, gRPC-string, nil, and unrelated error cases.

@github-actions
Copy link
Copy Markdown

⏱ Benchmark Results

No significant performance regressions detected.

benchstat comparison (baseline → PR)
## benchstat: baseline → PR
baseline-bench.txt:274: parsing iteration count: invalid syntax
baseline-bench.txt:301583: parsing iteration count: invalid syntax
baseline-bench.txt:578871: parsing iteration count: invalid syntax
baseline-bench.txt:1197832: parsing iteration count: invalid syntax
baseline-bench.txt:1509575: parsing iteration count: invalid syntax
baseline-bench.txt:1832127: parsing iteration count: invalid syntax
benchmark-results.txt:274: parsing iteration count: invalid syntax
benchmark-results.txt:382307: parsing iteration count: invalid syntax
benchmark-results.txt:752292: parsing iteration count: invalid syntax
benchmark-results.txt:1216540: parsing iteration count: invalid syntax
benchmark-results.txt:1567940: parsing iteration count: invalid syntax
benchmark-results.txt:1862496: parsing iteration count: invalid syntax
goos: linux
goarch: amd64
pkg: github.com/GoCodeAlone/workflow/dynamic
cpu: AMD EPYC 9V74 80-Core Processor                
                            │ benchmark-results.txt │
                            │        sec/op         │
InterpreterCreation-4                 2.592m ± 246%
ComponentLoad-4                       3.035m ±   5%
ComponentExecute-4                    1.548µ ±   2%
PoolContention/workers-1-4            876.9n ±   2%
PoolContention/workers-2-4            896.2n ±   6%
PoolContention/workers-4-4            870.6n ±   5%
PoolContention/workers-8-4            872.8n ±   4%
PoolContention/workers-16-4           936.0n ±   3%
ComponentLifecycle-4                  3.177m ±   3%
SourceValidation-4                    1.889µ ±   1%
RegistryConcurrent-4                  682.3n ±   7%
LoaderLoadFromString-4                3.014m ±   4%
geomean                               14.47µ

                            │ 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

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                            │ baseline-bench.txt │
                            │       sec/op       │
InterpreterCreation-4               7.278m ± 59%
ComponentLoad-4                     3.422m ±  0%
ComponentExecute-4                  1.885µ ±  2%
PoolContention/workers-1-4          1.160µ ±  2%
PoolContention/workers-2-4          1.181µ ±  2%
PoolContention/workers-4-4          1.185µ ±  2%
PoolContention/workers-8-4          1.163µ ±  1%
PoolContention/workers-16-4         1.167µ ±  0%
ComponentLifecycle-4                3.437m ±  1%
SourceValidation-4                  2.202µ ±  0%
RegistryConcurrent-4                859.4n ±  4%
LoaderLoadFromString-4              3.448m ±  1%
geomean                             19.07µ

                            │ 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

pkg: github.com/GoCodeAlone/workflow/middleware
cpu: AMD EPYC 9V74 80-Core Processor                
                                  │ benchmark-results.txt │
                                  │        sec/op         │
CircuitBreakerDetection-4                    267.7n ± 13%
CircuitBreakerExecution_Success-4            19.87n ±  2%
CircuitBreakerExecution_Failure-4            61.17n ±  2%
geomean                                      68.78n

                                  │ 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

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                  │ baseline-bench.txt │
                                  │       sec/op       │
CircuitBreakerDetection-4                  456.0n ± 4%
CircuitBreakerExecution_Success-4          59.70n ± 0%
CircuitBreakerExecution_Failure-4          64.83n ± 0%
geomean                                    120.8n

                                  │ 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

pkg: github.com/GoCodeAlone/workflow/module
cpu: AMD EPYC 9V74 80-Core Processor                
                                 │ benchmark-results.txt │
                                 │        sec/op         │
IaCStateBackend_InProcess-4                 257.6n ±  7%
IaCStateBackend_GRPC-4                      9.054m ± 18%
JQTransform_Simple-4                        594.8n ± 23%
JQTransform_ObjectConstruction-4            1.248µ ±  1%
JQTransform_ArraySelect-4                   3.036µ ±  3%
JQTransform_Complex-4                       38.67µ ±  2%
JQTransform_Throughput-4                    1.569µ ±  2%
SSEPublishDelivery-4                        57.32n ±  3%
geomean                                     3.410µ

                                 │ benchmark-results.txt │
                                 │         B/op          │
IaCStateBackend_InProcess-4                416.0 ±  0%
IaCStateBackend_GRPC-4                   5.716Mi ± 11%
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       │
IaCStateBackend_InProcess-4                 2.000 ± 0%
IaCStateBackend_GRPC-4                     6.868k ± 0%
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
                                 │ baseline-bench.txt │
                                 │       sec/op       │
IaCStateBackend_InProcess-4              342.2n ± 18%
IaCStateBackend_GRPC-4                   9.753m ±  3%
JQTransform_Simple-4                     688.0n ± 31%
JQTransform_ObjectConstruction-4         1.505µ ±  1%
JQTransform_ArraySelect-4                3.299µ ±  1%
JQTransform_Complex-4                    36.14µ ±  0%
JQTransform_Throughput-4                 1.835µ ±  1%
SSEPublishDelivery-4                     75.93n ±  0%
geomean                                  3.934µ

                                 │ baseline-bench.txt │
                                 │        B/op        │
IaCStateBackend_InProcess-4             416.0 ±  0%
IaCStateBackend_GRPC-4                5.708Mi ± 17%
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      │
IaCStateBackend_InProcess-4              2.000 ± 0%
IaCStateBackend_GRPC-4                  6.870k ± 0%
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                
                                    │ benchmark-results.txt │
                                    │        sec/op         │
SchemaValidation_Simple-4                      989.9n ± 11%
SchemaValidation_AllFields-4                   1.434µ ±  4%
SchemaValidation_FormatValidation-4            1.394µ ±  2%
SchemaValidation_ManySchemas-4                 1.433µ ±  2%
geomean                                        1.297µ

                                    │ 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

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                    │ baseline-bench.txt │
                                    │       sec/op       │
SchemaValidation_Simple-4                   1.024µ ± 23%
SchemaValidation_AllFields-4                1.529µ ±  1%
SchemaValidation_FormatValidation-4         1.493µ ±  1%
SchemaValidation_ManySchemas-4              1.508µ ±  3%
geomean                                     1.370µ

                                    │ 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

pkg: github.com/GoCodeAlone/workflow/store
cpu: AMD EPYC 9V74 80-Core Processor                
                                   │ benchmark-results.txt │
                                   │        sec/op         │
EventStoreAppend_InMemory-4                   953.4n ± 19%
EventStoreAppend_SQLite-4                     2.768m ± 32%
GetTimeline_InMemory/events-10-4              9.247µ ± 25%
GetTimeline_InMemory/events-50-4              50.44µ ±  2%
GetTimeline_InMemory/events-100-4             102.1µ ±  1%
GetTimeline_InMemory/events-500-4             522.9µ ±  2%
GetTimeline_InMemory/events-1000-4            1.057m ±  2%
GetTimeline_SQLite/events-10-4                78.02µ ±  3%
GetTimeline_SQLite/events-50-4                208.9µ ±  1%
GetTimeline_SQLite/events-100-4               370.0µ ±  4%
GetTimeline_SQLite/events-500-4               1.634m ±  2%
GetTimeline_SQLite/events-1000-4              3.035m ±  1%
geomean                                       189.0µ

                                   │ benchmark-results.txt │
                                   │         B/op          │
EventStoreAppend_InMemory-4                     837.5 ± 9%
EventStoreAppend_SQLite-4                     1.980Ki ± 4%
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

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                   │ baseline-bench.txt │
                                   │       sec/op       │
EventStoreAppend_InMemory-4                1.101µ ± 20%
EventStoreAppend_SQLite-4                  1.001m ±  4%
GetTimeline_InMemory/events-10-4           13.46µ ±  3%
GetTimeline_InMemory/events-50-4           73.67µ ±  5%
GetTimeline_InMemory/events-100-4          148.8µ ±  6%
GetTimeline_InMemory/events-500-4          597.7µ ±  0%
GetTimeline_InMemory/events-1000-4         1.224m ±  1%
GetTimeline_SQLite/events-10-4             81.27µ ±  1%
GetTimeline_SQLite/events-50-4             231.1µ ±  2%
GetTimeline_SQLite/events-100-4            418.5µ ±  1%
GetTimeline_SQLite/events-500-4            1.888m ±  1%
GetTimeline_SQLite/events-1000-4           3.698m ±  2%
geomean                                    207.9µ

                                   │ baseline-bench.txt │
                                   │        B/op        │
EventStoreAppend_InMemory-4                  786.5 ± 9%
EventStoreAppend_SQLite-4                  1.984Ki ± 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.32Ki

                                   │ 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

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

@intel352 intel352 merged commit c79dc5d into main May 20, 2026
27 checks passed
@intel352 intel352 deleted the fix/iac-notfound-grpc-1779263168 branch May 20, 2026 07:59
@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

❌ Patch coverage is 33.33333% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cmd/wfctl/infra_apply.go 33.33% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

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.

2 participants