Skip to content

fix(plugin/external): propagate plugin errors instead of swallowing as nil#515

Merged
intel352 merged 1 commit into
mainfrom
fix/adapter-error-propagation
May 2, 2026
Merged

fix(plugin/external): propagate plugin errors instead of swallowing as nil#515
intel352 merged 1 commit into
mainfrom
fix/adapter-error-propagation

Conversation

@intel352

@intel352 intel352 commented May 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes the diagnostic gap that hid two core-dump P1 schema mistakes behind a generic "factory returned nil" message during the 2026-05-02 deploy attempt (run 25244152181).

  • ExternalPluginAdapter.ModuleFactories() now returns an *errorModule (wrapping the actual plugin / gRPC error) instead of bare nil when CreateModule fails. StepFactories() already propagated both error paths correctly — no change needed there.
  • Adds AsModuleError(modular.Module) error and NewErrorModule(name, err) modular.Module exports so callers outside the package can surface and test factory failures without depending on the unexported type.
  • Extracts plugin discovery + load + ModuleFactories() into an injectable loadIaCPlugin var in cmd/wfctl/deploy_providers.go. discoverAndLoadIaCProvider now calls external.AsModuleError before the nil check; the bare-nil branch becomes a defensive backstop.

Engine and wfctl both already handle errorModule on the configErr branch — this is a uniform convention extension, not a new contract.

Test plan

  • TestModuleFactoriesPropagatesPluginError — fake gRPC client returns HandleResponse.Error; asserts returned module is *errorModule whose error contains the plugin's message.
  • TestResolveIaCProviderSurfacesPluginError — injected factory returns external.NewErrorModule; asserts discoverAndLoadIaCProvider returns error wrapping the plugin message.
  • Regression invariant proven for both tests (revert-and-restore): reverted adapter test got nil; reverted caller test got "does not support service invocation" instead of plugin message.
  • Existing plugin/external/... and cmd/wfctl/... test suites green.

🤖 Generated with Claude Code

…s nil

The external plugin adapter's ModuleFactories returned bare nil on any
CreateModule failure (gRPC error OR plugin-reported error in
createResp.Error). Callers got no signal about WHY the factory failed —
just a generic "iac.provider factory returned nil" message that hid the
actual plugin diagnostic.

This was the diagnostic gap that hid two core-dump P1 schema mistakes
behind a generic message during the 2026-05-02 first-deploy attempt.
The plugin had returned "digitalocean: missing required config key
'token'", but the operator saw "factory returned nil".

Fix: when CreateModule fails (gRPC error OR createResp.Error), return
an *errorModule wrapping the underlying message. Same pattern already
used for configErr a few lines earlier — this just extends it to the
remote-create-fail path. Engine and wfctl callers already handle
errorModule, so this is a uniform convention rather than a contract
change. (StepFactories already propagates both error paths correctly.)

Add exported helpers AsModuleError + NewErrorModule so callers in other
packages can surface and simulate factory failures without depending on
the unexported errorModule type.

Caller in cmd/wfctl/deploy_providers.go: extract findIaCPluginDir +
plugin load + ModuleFactories into a loadIaCPlugin var (injectable for
tests). discoverAndLoadIaCProvider now calls external.AsModuleError to
detect the *errorModule before the nil check; surfaces the wrapped error
message. Bare-nil branch becomes a defensive backstop with "file an
issue" hint.

Regression invariant proven for both tests: with fix reverted,
TestModuleFactoriesPropagatesPluginError got nil (swallowed);
TestResolveIaCProviderSurfacesPluginError got wrong error
("does not support service invocation" instead of plugin message).

See docs/plans/2026-05-02-wfctl-bootstrap-diagnostics-design.md PR 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 2, 2026 06:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 improves diagnostics for external IaC plugins by ensuring plugin-reported CreateModule failures propagate as actionable errors (via a non-nil sentinel module) instead of being swallowed and later surfacing as generic “factory returned nil”/type assertion failures in wfctl.

Changes:

  • Update ExternalPluginAdapter.ModuleFactories() to return an errorModule (carrying the underlying gRPC/plugin error) when CreateModule fails or the plugin returns a non-empty HandleResponse.Error.
  • Export external.AsModuleError(modular.Module) error and external.NewErrorModule(name, err) modular.Module so callers/tests can detect/simulate factory failures without referencing an unexported type.
  • Refactor wfctl IaC plugin discovery/load into an injectable loadIaCPlugin and ensure discoverAndLoadIaCProvider checks external.AsModuleError before the nil-module backstop.

Reviewed changes

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

File Description
plugin/external/adapter.go Propagates CreateModule failures via errorModule; adds exported helpers to detect/simulate factory errors.
plugin/external/adapter_test.go Adds regression test ensuring plugin HandleResponse.Error is not swallowed as nil.
cmd/wfctl/deploy_providers.go Makes IaC plugin load injectable and surfaces errorModule failures as clear user-facing errors.
cmd/wfctl/deploy_providers_test.go Adds regression test ensuring wfctl returns the plugin’s diagnostic message when factory creation fails.

@intel352
intel352 merged commit 1876c7a into main May 2, 2026
21 of 22 checks passed
@intel352
intel352 deleted the fix/adapter-error-propagation branch May 2, 2026 06:36
@github-actions

github-actions Bot commented May 2, 2026

Copy link
Copy Markdown

⏱ Benchmark Results

No significant performance regressions detected.

benchstat comparison (baseline → PR)
## benchstat: baseline → PR
baseline-bench.txt:245: parsing iteration count: invalid syntax
baseline-bench.txt:349551: parsing iteration count: invalid syntax
baseline-bench.txt:654421: parsing iteration count: invalid syntax
baseline-bench.txt:950159: parsing iteration count: invalid syntax
baseline-bench.txt:1267767: parsing iteration count: invalid syntax
baseline-bench.txt:1581673: parsing iteration count: invalid syntax
benchmark-results.txt:245: parsing iteration count: invalid syntax
benchmark-results.txt:286677: parsing iteration count: invalid syntax
benchmark-results.txt:602245: parsing iteration count: invalid syntax
benchmark-results.txt:902675: parsing iteration count: invalid syntax
benchmark-results.txt:1409658: parsing iteration count: invalid syntax
benchmark-results.txt:1924396: parsing iteration count: invalid syntax
goos: linux
goarch: amd64
pkg: github.com/GoCodeAlone/workflow/dynamic
cpu: AMD EPYC 7763 64-Core Processor                
                            │ benchmark-results.txt │
                            │        sec/op         │
InterpreterCreation-4                 3.396m ± 192%
ComponentLoad-4                       3.678m ±   2%
ComponentExecute-4                    1.965µ ±   1%
PoolContention/workers-1-4            1.115µ ±   1%
PoolContention/workers-2-4            1.106µ ±   1%
PoolContention/workers-4-4            1.106µ ±   1%
PoolContention/workers-8-4            1.111µ ±   1%
PoolContention/workers-16-4           1.120µ ±   1%
ComponentLifecycle-4                  3.672m ±   1%
SourceValidation-4                    2.292µ ±   1%
RegistryConcurrent-4                  814.0n ±   4%
LoaderLoadFromString-4                3.695m ±   2%
geomean                               17.86µ

                            │ 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: AMD EPYC 9V74 80-Core Processor                
                            │ baseline-bench.txt │
                            │       sec/op       │
InterpreterCreation-4              2.993m ± 199%
ComponentLoad-4                    3.500m ±  12%
ComponentExecute-4                 1.811µ ±   2%
PoolContention/workers-1-4         1.020µ ±   2%
PoolContention/workers-2-4         1.014µ ±   1%
PoolContention/workers-4-4         1.018µ ±   2%
PoolContention/workers-8-4         1.020µ ±   1%
PoolContention/workers-16-4        1.016µ ±   1%
ComponentLifecycle-4               3.522m ±   1%
SourceValidation-4                 2.071µ ±   1%
RegistryConcurrent-4               742.8n ±   3%
LoaderLoadFromString-4             3.566m ±   1%
geomean                            16.47µ

                            │ 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 7763 64-Core Processor                
                                  │ benchmark-results.txt │
                                  │        sec/op         │
CircuitBreakerDetection-4                     291.1n ± 2%
CircuitBreakerExecution_Success-4             21.52n ± 0%
CircuitBreakerExecution_Failure-4             66.23n ± 0%
geomean                                       74.59n

                                  │ 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: AMD EPYC 9V74 80-Core Processor                
                                  │ baseline-bench.txt │
                                  │       sec/op       │
CircuitBreakerDetection-4                 297.9n ± 13%
CircuitBreakerExecution_Success-4         22.66n ±  0%
CircuitBreakerExecution_Failure-4         71.00n ±  0%
geomean                                   78.26n

                                  │ 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 7763 64-Core Processor                
                                 │ benchmark-results.txt │
                                 │        sec/op         │
JQTransform_Simple-4                        893.5n ± 31%
JQTransform_ObjectConstruction-4            1.471µ ± 26%
JQTransform_ArraySelect-4                   3.394µ ±  1%
JQTransform_Complex-4                       38.95µ ±  2%
JQTransform_Throughput-4                    1.784µ ±  1%
SSEPublishDelivery-4                        71.89n ±  1%
geomean                                     1.677µ

                                 │ 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

cpu: AMD EPYC 9V74 80-Core Processor                
                                 │ baseline-bench.txt │
                                 │       sec/op       │
JQTransform_Simple-4                     807.7n ± 30%
JQTransform_ObjectConstruction-4         1.365µ ±  1%
JQTransform_ArraySelect-4                3.304µ ±  1%
JQTransform_Complex-4                    41.04µ ±  1%
JQTransform_Throughput-4                 1.674µ ±  1%
SSEPublishDelivery-4                     63.89n ±  1%
geomean                                  1.587µ

                                 │ 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

pkg: github.com/GoCodeAlone/workflow/schema
cpu: AMD EPYC 7763 64-Core Processor                
                                    │ benchmark-results.txt │
                                    │        sec/op         │
SchemaValidation_Simple-4                       1.111µ ± 7%
SchemaValidation_AllFields-4                    1.667µ ± 1%
SchemaValidation_FormatValidation-4             1.581µ ± 1%
SchemaValidation_ManySchemas-4                  1.819µ ± 3%
geomean                                         1.519µ

                                    │ 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: AMD EPYC 9V74 80-Core Processor                
                                    │ baseline-bench.txt │
                                    │       sec/op       │
SchemaValidation_Simple-4                   1.118µ ± 17%
SchemaValidation_AllFields-4                1.663µ ±  5%
SchemaValidation_FormatValidation-4         1.607µ ±  2%
SchemaValidation_ManySchemas-4              1.621µ ±  2%
geomean                                     1.483µ

                                    │ 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 7763 64-Core Processor                
                                   │ benchmark-results.txt │
                                   │        sec/op         │
EventStoreAppend_InMemory-4                   1.225µ ±  8%
EventStoreAppend_SQLite-4                     1.356m ± 11%
GetTimeline_InMemory/events-10-4              14.10µ ±  3%
GetTimeline_InMemory/events-50-4              79.53µ ±  2%
GetTimeline_InMemory/events-100-4             158.7µ ±  2%
GetTimeline_InMemory/events-500-4             825.4µ ±  2%
GetTimeline_InMemory/events-1000-4            1.465m ± 17%
GetTimeline_SQLite/events-10-4                119.5µ ±  2%
GetTimeline_SQLite/events-50-4                262.7µ ±  2%
GetTimeline_SQLite/events-100-4               436.8µ ±  1%
GetTimeline_SQLite/events-500-4               1.872m ±  1%
GetTimeline_SQLite/events-1000-4              3.628m ±  1%
geomean                                       238.1µ

                                   │ benchmark-results.txt │
                                   │         B/op          │
EventStoreAppend_InMemory-4                    760.0 ± 12%
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.12Ki

                                   │ 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: AMD EPYC 9V74 80-Core Processor                
                                   │ baseline-bench.txt │
                                   │       sec/op       │
EventStoreAppend_InMemory-4                1.103µ ± 18%
EventStoreAppend_SQLite-4                  1.054m ±  4%
GetTimeline_InMemory/events-10-4           12.30µ ±  2%
GetTimeline_InMemory/events-50-4           67.65µ ± 21%
GetTimeline_InMemory/events-100-4          106.7µ ±  1%
GetTimeline_InMemory/events-500-4          547.3µ ±  1%
GetTimeline_InMemory/events-1000-4         1.121m ±  7%
GetTimeline_SQLite/events-10-4             85.56µ ±  1%
GetTimeline_SQLite/events-50-4             220.4µ ±  1%
GetTimeline_SQLite/events-100-4            382.8µ ±  0%
GetTimeline_SQLite/events-500-4            1.663m ±  0%
GetTimeline_SQLite/events-1000-4           3.241m ±  1%
geomean                                    191.7µ

                                   │ baseline-bench.txt │
                                   │        B/op        │
EventStoreAppend_InMemory-4                 773.0 ± 11%
EventStoreAppend_SQLite-4                 1.986Ki ±  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.23Ki

                                   │ 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.

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