Skip to content

feat: add -plugin-dir flag to wfctl infra commands#647

Merged
intel352 merged 3 commits into
mainfrom
copilot/add-plugin-dir-override-infra-commands
May 13, 2026
Merged

feat: add -plugin-dir flag to wfctl infra commands#647
intel352 merged 3 commits into
mainfrom
copilot/add-plugin-dir-override-infra-commands

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 13, 2026

wfctl plugin install accepted -plugin-dir but wfctl infra apply (and all other infra commands that load external plugins) did not, making isolated CI verification with a custom plugin directory impossible.

Approach

Added a currentInfraPluginDir package-level seam variable in deploy_providers.go (same pattern as currentApplyIncludeFlag). discoverAndLoadIaCProvider now checks it before WFCTL_PLUGIN_DIR and the ./data/plugins default.

All commands use a save/restore pattern (prevInfraPluginDir := currentInfraPluginDir; defer func() { currentInfraPluginDir = prevInfraPluginDir }()) rather than a hard reset to "". This correctly handles runInfraApply calling runInfraBootstrap as a sub-call — bootstrap's deferred restore returns the parent's plugin dir rather than clobbering it with "".

Changes

  • deploy_providers.go — add currentInfraPluginDir seam var; check it first in discoverAndLoadIaCProvider
  • infra.go — add -plugin-dir to plan, apply, status, drift, destroy, import; thread --plugin-dir through bootstrap sub-call args
  • infra_bootstrap.go — add -plugin-dir to bootstrap
  • infra_refresh_outputs.go — add -plugin-dir to refresh-outputs
  • infra_cleanup.go — add -plugin-dir to cleanup
  • infra_align.go — add -plugin-dir to align
  • infra_audit_keys.go — add -plugin-dir to audit-keys
  • infra_prune.go — add -plugin-dir to prune
  • infra_rotate_and_prune.go — add -plugin-dir to rotate-and-prune
  • infra_plugin_dir_test.go (new) — verifies flag acceptance, correct seam threading, post-command reset, and precedence over WFCTL_PLUGIN_DIR for all major commands including bootstrap and refresh-outputs
  • docs/WFCTL.md — documents --plugin-dir in all affected command tables

Usage

# Install a clean plugin set into an isolated directory
wfctl plugin install my-provider --plugin-dir /tmp/ci-plugins

# Run dry-run against that isolated directory — previously failed with
# "flag provided but not defined: -plugin-dir"
wfctl infra apply --dry-run --plugin-dir /tmp/ci-plugins -c infra.yaml
wfctl infra plan  --plugin-dir /tmp/ci-plugins -c infra.yaml
wfctl infra bootstrap --plugin-dir /tmp/ci-plugins -c infra.yaml
wfctl infra refresh-outputs --plugin-dir /tmp/ci-plugins -c infra.yaml

Priority order for plugin directory resolution: -plugin-dir flag → WFCTL_PLUGIN_DIR env var → ./data/plugins default.

Copilot AI requested review from Copilot and removed request for Copilot May 13, 2026 05:54
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 13, 2026

⏱ Benchmark Results

No significant performance regressions detected.

benchstat comparison (baseline → PR)
## benchstat: baseline → PR
baseline-bench.txt:264: parsing iteration count: invalid syntax
baseline-bench.txt:291409: parsing iteration count: invalid syntax
baseline-bench.txt:558851: parsing iteration count: invalid syntax
baseline-bench.txt:1096044: parsing iteration count: invalid syntax
baseline-bench.txt:1386271: parsing iteration count: invalid syntax
baseline-bench.txt:1660442: parsing iteration count: invalid syntax
benchmark-results.txt:264: parsing iteration count: invalid syntax
benchmark-results.txt:319789: parsing iteration count: invalid syntax
benchmark-results.txt:612695: parsing iteration count: invalid syntax
benchmark-results.txt:904713: parsing iteration count: invalid syntax
benchmark-results.txt:1197337: parsing iteration count: invalid syntax
benchmark-results.txt:1523399: parsing iteration count: invalid syntax
goos: linux
goarch: amd64
pkg: github.com/GoCodeAlone/workflow/dynamic
cpu: AMD EPYC 7763 64-Core Processor                
                            │ baseline-bench.txt │       benchmark-results.txt        │
                            │       sec/op       │    sec/op     vs base              │
InterpreterCreation-4               7.657m ± 59%   6.641m ± 68%       ~ (p=0.937 n=6)
ComponentLoad-4                     3.575m ±  0%   3.563m ± 14%       ~ (p=0.394 n=6)
ComponentExecute-4                  1.924µ ±  1%   1.919µ ±  0%       ~ (p=0.095 n=6)
PoolContention/workers-1-4          1.089µ ±  1%   1.076µ ±  1%  -1.19% (p=0.030 n=6)
PoolContention/workers-2-4          1.074µ ±  4%   1.077µ ±  2%       ~ (p=0.556 n=6)
PoolContention/workers-4-4          1.081µ ±  1%   1.080µ ±  1%       ~ (p=0.851 n=6)
PoolContention/workers-8-4          1.083µ ±  2%   1.080µ ±  0%       ~ (p=0.290 n=6)
PoolContention/workers-16-4         1.092µ ±  1%   1.088µ ±  1%       ~ (p=0.258 n=6)
ComponentLifecycle-4                3.644m ±  1%   3.596m ±  1%  -1.32% (p=0.015 n=6)
SourceValidation-4                  2.317µ ±  2%   2.306µ ±  1%  -0.43% (p=0.011 n=6)
RegistryConcurrent-4                807.9n ±  3%   809.1n ±  4%       ~ (p=0.818 n=6)
LoaderLoadFromString-4              3.659m ±  1%   3.590m ±  1%  -1.87% (p=0.002 n=6)
geomean                             18.81µ         18.50µ        -1.66%

                            │ baseline-bench.txt │        benchmark-results.txt         │
                            │        B/op        │     B/op      vs base                │
InterpreterCreation-4               2.027Mi ± 0%   2.027Mi ± 0%       ~ (p=0.738 n=6)
ComponentLoad-4                     2.180Mi ± 0%   2.180Mi ± 0%       ~ (p=0.457 n=6)
ComponentExecute-4                  1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-1-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-2-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-4-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-8-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-16-4         1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
ComponentLifecycle-4                2.183Mi ± 0%   2.183Mi ± 0%       ~ (p=0.784 n=6)
SourceValidation-4                  1.984Ki ± 0%   1.984Ki ± 0%       ~ (p=1.000 n=6) ¹
RegistryConcurrent-4                1.133Ki ± 0%   1.133Ki ± 0%       ~ (p=1.000 n=6) ¹
LoaderLoadFromString-4              2.182Mi ± 0%   2.182Mi ± 0%       ~ (p=0.190 n=6)
geomean                             15.25Ki        15.25Ki       -0.00%
¹ all samples are equal

                            │ baseline-bench.txt │        benchmark-results.txt        │
                            │     allocs/op      │  allocs/op   vs base                │
InterpreterCreation-4                15.68k ± 0%   15.68k ± 0%       ~ (p=1.000 n=6)
ComponentLoad-4                      18.02k ± 0%   18.02k ± 0%       ~ (p=1.000 n=6)
ComponentExecute-4                    25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-1-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-2-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-4-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-8-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-16-4           25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
ComponentLifecycle-4                 18.07k ± 0%   18.07k ± 0%       ~ (p=1.000 n=6) ¹
SourceValidation-4                    32.00 ± 0%    32.00 ± 0%       ~ (p=1.000 n=6) ¹
RegistryConcurrent-4                  2.000 ± 0%    2.000 ± 0%       ~ (p=1.000 n=6) ¹
LoaderLoadFromString-4               18.06k ± 0%   18.06k ± 0%       ~ (p=1.000 n=6) ¹
geomean                               183.3         183.3       +0.00%
¹ all samples are equal

pkg: github.com/GoCodeAlone/workflow/middleware
                                  │ baseline-bench.txt │       benchmark-results.txt       │
                                  │       sec/op       │   sec/op     vs base              │
CircuitBreakerDetection-4                  286.7n ± 5%   284.9n ± 2%  -0.63% (p=0.024 n=6)
CircuitBreakerExecution_Success-4          21.38n ± 1%   21.36n ± 0%       ~ (p=0.407 n=6)
CircuitBreakerExecution_Failure-4          66.81n ± 0%   66.23n ± 0%  -0.87% (p=0.002 n=6)
geomean                                    74.26n        73.86n       -0.54%

                                  │ baseline-bench.txt │       benchmark-results.txt        │
                                  │        B/op        │    B/op     vs base                │
CircuitBreakerDetection-4                 144.0 ± 0%     144.0 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Success-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Failure-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                              ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                  │ baseline-bench.txt │       benchmark-results.txt        │
                                  │     allocs/op      │ allocs/op   vs base                │
CircuitBreakerDetection-4                 1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Success-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Failure-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                              ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/module
                                 │ baseline-bench.txt │       benchmark-results.txt        │
                                 │       sec/op       │    sec/op     vs base              │
JQTransform_Simple-4                     869.8n ± 27%   946.0n ± 16%       ~ (p=0.699 n=6)
JQTransform_ObjectConstruction-4         1.434µ ±  2%   1.421µ ±  0%  -0.87% (p=0.002 n=6)
JQTransform_ArraySelect-4                3.325µ ±  2%   3.285µ ±  1%  -1.19% (p=0.002 n=6)
JQTransform_Complex-4                    38.52µ ±  1%   37.79µ ±  1%  -1.92% (p=0.002 n=6)
JQTransform_Throughput-4                 1.760µ ±  1%   1.738µ ±  1%  -1.22% (p=0.004 n=6)
SSEPublishDelivery-4                     62.74n ±  1%   62.81n ±  0%       ~ (p=0.846 n=6)
geomean                                  1.613µ         1.622µ        +0.55%

                                 │ baseline-bench.txt │        benchmark-results.txt         │
                                 │        B/op        │     B/op      vs base                │
JQTransform_Simple-4                   1.273Ki ± 0%     1.273Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ObjectConstruction-4       1.773Ki ± 0%     1.773Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ArraySelect-4              2.625Ki ± 0%     2.625Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Complex-4                  16.22Ki ± 0%     16.22Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Throughput-4               1.984Ki ± 0%     1.984Ki ± 0%       ~ (p=1.000 n=6) ¹
SSEPublishDelivery-4                     0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                             ²                 +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                 │ baseline-bench.txt │       benchmark-results.txt        │
                                 │     allocs/op      │ allocs/op   vs base                │
JQTransform_Simple-4                     10.00 ± 0%     10.00 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ObjectConstruction-4         15.00 ± 0%     15.00 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ArraySelect-4                30.00 ± 0%     30.00 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Complex-4                    324.0 ± 0%     324.0 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Throughput-4                 17.00 ± 0%     17.00 ± 0%       ~ (p=1.000 n=6) ¹
SSEPublishDelivery-4                     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                             ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/schema
                                    │ baseline-bench.txt │       benchmark-results.txt        │
                                    │       sec/op       │    sec/op     vs base              │
SchemaValidation_Simple-4                   1.105µ ±  2%   1.126µ ± 13%       ~ (p=0.132 n=6)
SchemaValidation_AllFields-4                1.666µ ± 25%   1.644µ ±  1%  -1.35% (p=0.045 n=6)
SchemaValidation_FormatValidation-4         1.587µ ±  1%   1.588µ ±  1%       ~ (p=0.788 n=6)
SchemaValidation_ManySchemas-4              1.836µ ±  1%   1.814µ ±  2%       ~ (p=0.240 n=6)
geomean                                     1.521µ         1.519µ        -0.14%

                                    │ baseline-bench.txt │       benchmark-results.txt        │
                                    │        B/op        │    B/op     vs base                │
SchemaValidation_Simple-4                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_AllFields-4                0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_FormatValidation-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_ManySchemas-4              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                    │ baseline-bench.txt │       benchmark-results.txt        │
                                    │     allocs/op      │ allocs/op   vs base                │
SchemaValidation_Simple-4                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_AllFields-4                0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_FormatValidation-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_ManySchemas-4              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/store
                                   │ baseline-bench.txt │       benchmark-results.txt        │
                                   │       sec/op       │    sec/op     vs base              │
EventStoreAppend_InMemory-4                1.218µ ± 14%   1.198µ ± 18%       ~ (p=0.621 n=6)
EventStoreAppend_SQLite-4                  1.259m ±  5%   1.299m ±  9%       ~ (p=0.132 n=6)
GetTimeline_InMemory/events-10-4           13.48µ ±  3%   13.73µ ±  3%       ~ (p=0.310 n=6)
GetTimeline_InMemory/events-50-4           76.33µ ±  1%   69.10µ ± 15%       ~ (p=0.699 n=6)
GetTimeline_InMemory/events-100-4          121.9µ ± 27%   123.2µ ±  1%       ~ (p=0.394 n=6)
GetTimeline_InMemory/events-500-4          624.7µ ±  0%   633.3µ ±  1%  +1.38% (p=0.002 n=6)
GetTimeline_InMemory/events-1000-4         1.271m ±  1%   1.289m ±  2%  +1.41% (p=0.002 n=6)
GetTimeline_SQLite/events-10-4             106.9µ ±  1%   106.0µ ±  1%       ~ (p=0.132 n=6)
GetTimeline_SQLite/events-50-4             247.6µ ±  1%   248.3µ ±  1%       ~ (p=0.310 n=6)
GetTimeline_SQLite/events-100-4            416.4µ ±  1%   419.0µ ±  2%  +0.62% (p=0.026 n=6)
GetTimeline_SQLite/events-500-4            1.769m ±  1%   1.786m ±  1%  +0.97% (p=0.002 n=6)
GetTimeline_SQLite/events-1000-4           3.460m ±  1%   3.478m ±  1%  +0.52% (p=0.041 n=6)
geomean                                    216.0µ         215.8µ        -0.10%

                                   │ baseline-bench.txt │        benchmark-results.txt         │
                                   │        B/op        │     B/op      vs base                │
EventStoreAppend_InMemory-4                  812.0 ± 5%     788.0 ± 5%       ~ (p=0.195 n=6)
EventStoreAppend_SQLite-4                  1.985Ki ± 2%   1.987Ki ± 0%       ~ (p=0.725 n=6)
GetTimeline_InMemory/events-10-4           7.953Ki ± 0%   7.953Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-50-4           46.62Ki ± 0%   46.62Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-100-4          94.48Ki ± 0%   94.48Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-500-4          472.8Ki ± 0%   472.8Ki ± 0%       ~ (p=0.080 n=6)
GetTimeline_InMemory/events-1000-4         944.3Ki ± 0%   944.3Ki ± 0%       ~ (p=0.197 n=6)
GetTimeline_SQLite/events-10-4             16.74Ki ± 0%   16.74Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-50-4             87.14Ki ± 0%   87.14Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-100-4            175.4Ki ± 0%   175.4Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-500-4            846.1Ki ± 0%   846.1Ki ± 0%       ~ (p=0.470 n=6)
GetTimeline_SQLite/events-1000-4           1.639Mi ± 0%   1.639Mi ± 0%       ~ (p=0.870 n=6)
geomean                                    67.50Ki        67.34Ki       -0.24%
¹ all samples are equal

                                   │ baseline-bench.txt │        benchmark-results.txt        │
                                   │     allocs/op      │  allocs/op   vs base                │
EventStoreAppend_InMemory-4                  7.000 ± 0%    7.000 ± 0%       ~ (p=1.000 n=6) ¹
EventStoreAppend_SQLite-4                    53.00 ± 0%    53.00 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-10-4             125.0 ± 0%    125.0 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-50-4             653.0 ± 0%    653.0 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-100-4           1.306k ± 0%   1.306k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-500-4           6.514k ± 0%   6.514k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-1000-4          13.02k ± 0%   13.02k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-10-4               382.0 ± 0%    382.0 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-50-4              1.852k ± 0%   1.852k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-100-4             3.681k ± 0%   3.681k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-500-4             18.54k ± 0%   18.54k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-1000-4            37.29k ± 0%   37.29k ± 0%       ~ (p=1.000 n=6) ¹
geomean                                     1.162k        1.162k       +0.00%
¹ all samples are equal

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

@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2026

Codecov Report

❌ Patch coverage is 71.42857% with 20 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cmd/wfctl/infra.go 53.12% 15 Missing ⚠️
cmd/wfctl/infra_align.go 0.00% 5 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copilot AI requested review from Copilot and removed request for Copilot May 13, 2026 06:16
Copilot AI changed the title [WIP] Add plugin-dir override support for wfctl infra commands feat: add -plugin-dir flag to wfctl infra commands May 13, 2026
Copilot AI requested a review from intel352 May 13, 2026 06:19
@intel352 intel352 marked this pull request as ready for review May 13, 2026 06:30
Copilot AI review requested due to automatic review settings May 13, 2026 06:30
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

Adds a --plugin-dir override to wfctl infra subcommands so CI (and local smoke tests) can load IaC provider plugins from an isolated directory, with precedence --plugin-dirWFCTL_PLUGIN_DIR./data/plugins.

Changes:

  • Introduces a per-invocation currentInfraPluginDir seam and updates IaC provider discovery to consult it first.
  • Registers --plugin-dir across the main infra plugin-loading subcommands and threads the value via currentInfraPluginDir.
  • Adds a new test suite to verify flag acceptance, seam propagation, and post-command reset; updates docs/WFCTL.md accordingly.

Reviewed changes

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

Show a summary per file
File Description
docs/WFCTL.md Documents --plugin-dir for infra commands and adds CI usage examples.
cmd/wfctl/infra.go Adds --plugin-dir flag and publishes it via currentInfraPluginDir for plan/apply/status/drift/destroy/import.
cmd/wfctl/infra_rotate_and_prune.go Adds --plugin-dir flag + seam publish/reset for rotate-and-prune.
cmd/wfctl/infra_prune.go Adds --plugin-dir flag + seam publish/reset for prune.
cmd/wfctl/infra_plugin_dir_test.go New tests ensuring --plugin-dir is accepted and correctly influences provider loading.
cmd/wfctl/infra_cleanup.go Adds --plugin-dir flag + seam publish/reset for cleanup.
cmd/wfctl/infra_audit_keys.go Adds --plugin-dir flag + seam publish/reset for audit-keys.
cmd/wfctl/infra_align.go Adds --plugin-dir flag + seam publish/reset for align.
cmd/wfctl/deploy_providers.go Adds currentInfraPluginDir seam and makes provider discovery prefer it over env/default.

Comment thread docs/WFCTL.md Outdated
| `--parallelism` | `10` | Number of parallel operations |
| `--lock-timeout` | `0s` | Timeout for state lock acquisition |
| `--force-rotate` | `` | (`bootstrap` only) Comma-separated list of secret names to regenerate, replacing existing values. Repeatable. Use to recover from known-bad secrets (empty value, leaked, dead key). Refuses `provider_credential` types. |
| `--plugin-dir` | _(env `WFCTL_PLUGIN_DIR` or `data/plugins`)_ | Override the plugin directory for plugin-loading commands (plan, apply, status, drift, destroy, import, cleanup, align, audit-keys, prune, rotate-and-prune). Useful for isolated CI smoke tests. |
Comment thread cmd/wfctl/infra.go Outdated
Comment on lines +246 to +252
var pluginDirFlag string
fs.StringVar(&pluginDirFlag, "plugin-dir", "", "Plugin directory (overrides WFCTL_PLUGIN_DIR and default data/plugins)")
if err := fs.Parse(args); err != nil {
return err
}
currentInfraPluginDir = pluginDirFlag
defer func() { currentInfraPluginDir = "" }()
@intel352
Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Test coverage is also lacking: #647 (comment)

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 13, 2026

@copilot apply changes based on the comments in this thread

Test coverage is also lacking: https:/...

Added --plugin-dir to runInfraBootstrap and runInfraRefreshOutputs in commit e855adb.

Also fixed a subtle interaction: runInfraApply calls runInfraBootstrap as a sub-call, so switching from a hard-reset (defer func() { currentInfraPluginDir = "" }()) to a save/restore pattern (prevInfraPluginDir := currentInfraPluginDir; defer func() { currentInfraPluginDir = prevInfraPluginDir }()) ensures the parent's plugin dir is preserved when bootstrap returns. The --plugin-dir value is also threaded through the bootstrap sub-call args.

Tests were added for both bootstrap and refresh-outputs in infra_plugin_dir_test.go.

@intel352 intel352 merged commit 96408f0 into main May 13, 2026
23 checks passed
@intel352 intel352 deleted the copilot/add-plugin-dir-override-infra-commands branch May 13, 2026 23:30
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 infra commands should support plugin-dir override for isolated verification

3 participants