Skip to content

feat(wfctl): secrets setup --plugin reads plugin-declared required_secrets[]#737

Closed
intel352 wants to merge 1 commit into
mainfrom
feat/secrets-setup-plugin-1779276451
Closed

feat(wfctl): secrets setup --plugin reads plugin-declared required_secrets[]#737
intel352 wants to merge 1 commit into
mainfrom
feat/secrets-setup-plugin-1779276451

Conversation

@intel352
Copy link
Copy Markdown
Contributor

Per workflow#735 SPEC T3+T4. Reads plugin.json required_secrets[], prompts each (masked iff sensitive), writes to chosen GH scope. 7 tests.

Implements T3+T4 of docs/plans/2026-05-20-dns-providers.md.

`wfctl secrets setup --plugin workflow-plugin-hover --scope org
  --org GoCodeAlone --token-env GH_PAT` reads plugin.json from the
configured plugin install dir, prompts for each required_secrets[]
entry (masked iff sensitive), and writes the values to the chosen
GitHub scope (repo|env|org) via the new scoped GH provider.

cmd/wfctl/secrets_setup_plugin.go:
- pluginManifest + PluginRequiredSecret types (json:"required_secrets").
- runSecretsSetupPlugin + runSecretsSetupPluginWithIO (testable core
  accepts injectable io.Reader for piped input).
- loadPluginManifest: resolves plugin install dir from
  --plugin-dir / $WFCTL_PLUGIN_DIR / ./data/plugins; reads
  plugin.json; errors hint at `wfctl plugin install` when missing.
- promptOne: piped path returns the line as-is; sensitive
  interactive path uses term.ReadPassword; non-sensitive
  interactive uses bare Fscanln.
- buildSecretWriter: switches on scope (org|env|repo) and mints
  the matching GitHub provider. Fails loud on missing --org/--env.

cmd/wfctl/secrets.go: dispatch updated — when `secrets setup`
sees a --plugin arg, route to runSecretsSetupPlugin instead of
the env-based runSecretsSetup.

7 new tests:
- LoadPluginManifest happy + missing-dir (hint) + bad JSON.
- promptOne piped non-sensitive + sensitive.
- RunSecretsSetupPlugin: piped reader writes through; emits prelude.
- BuildSecretWriter scope routing: org happy, missing --org/--env
  errors, unknown scope errors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 20, 2026 11:33
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 new wfctl secrets setup --plugin <name> workflow to read a plugin’s plugin.json.required_secrets[], prompt for each secret (masked when interactive + sensitive=true), and write values to a chosen GitHub secrets scope.

Changes:

  • Dispatch wfctl secrets setup to a new --plugin-driven path.
  • Implement secrets setup --plugin manifest loading, prompting, and scoped GitHub secret writing.
  • Add unit tests covering manifest parsing, prompt behavior, and basic scope routing.

Reviewed changes

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

File Description
cmd/wfctl/secrets.go Routes secrets setup to the plugin-based setup flow when --plugin is present.
cmd/wfctl/secrets_setup_plugin.go New implementation for reading required_secrets[], prompting, and writing to GitHub repo/env/org secrets.
cmd/wfctl/secrets_setup_plugin_test.go New tests for manifest loading, prompting, and writer scope selection.
Comments suppressed due to low confidence (2)

cmd/wfctl/secrets_setup_plugin.go:171

  • Non-sensitive interactive input uses fmt.Fscanln(os.Stdin, &line), which tokenizes on whitespace and will truncate values that contain spaces. This also differs from runSecretsSetup which reads full lines via bufio.Reader.ReadString('\n'). Prefer line-based reading here too (and keep the empty-line skip behavior).
	// Non-sensitive interactive — echo.
	var line string
	if _, err := fmt.Fscanln(os.Stdin, &line); err != nil && err.Error() != "unexpected newline" {
		return "", err
	}
	return line, nil

cmd/wfctl/secrets_setup_plugin_test.go:136

  • TestRunSecretsSetupPlugin_PiperReadsRequiredSecrets doesn't assert that each required secret is read separately and written via the provider; it only checks that a non-nil error occurs and that the prelude was printed. This test won't catch regressions like consuming multiple lines at once or skipping later secrets. Consider injecting a fake scopedWriter (or a factory) so the test can assert Set calls/values without hitting the network.
func TestRunSecretsSetupPlugin_PiperReadsRequiredSecrets(t *testing.T) {
	dir := t.TempDir()
	writePluginManifestFile(t, dir, "wp-fake", `{
		"name": "wp-fake",
		"required_secrets": [
			{"name": "A", "sensitive": false},
			{"name": "B", "sensitive": true}
		]
	}`)
	// Stub the writer side by setting the org via env so
	// buildSecretWriter is short-circuited (we just want to exercise
	// the prompt loop). Use --scope=org with a stub provider not
	// reachable in tests; the call will fail at network → we assert
	// we got at least to the writer construction.
	in := io.Reader(strings.NewReader("alice\nhunter2\n"))
	var out bytes.Buffer
	t.Setenv("GITHUB_TOKEN", "stub")

	// We can't actually hit the GH API; use --scope=org pointing
	// at a non-resolvable token+org, then assert error returns from
	// the network-side path (after the prompts succeed).
	err := runSecretsSetupPluginWithIO([]string{
		"--plugin", "wp-fake",
		"--plugin-dir", dir,
		"--scope", "org",
		"--org", "test-org",
		"--token-env", "GITHUB_TOKEN",
	}, in, &out)
	if err == nil {
		t.Fatal("expected network-side error reaching GH (test runs offline)")
	}
	// The output buffer should still show that we entered the setup
	// loop (prompt prelude).
	if !strings.Contains(out.String(), "Setting up secrets for plugin") {
		t.Errorf("setup prelude missing from output:\n%s", out.String())
	}
}

Comment on lines +145 to +149
// Test/piped path — read one line.
buf := make([]byte, 4096)
n, err := in.Read(buf)
if err != nil && err != io.EOF {
return "", err
Comment on lines +112 to +120
dir := dirOverride
if dir == "" {
dir = os.Getenv("WFCTL_PLUGIN_DIR")
}
if dir == "" {
dir = "./data/plugins"
}
path := filepath.Join(dir, name, "plugin.json")
data, err := os.ReadFile(path)
vis, err := parseGitHubOrgVisibility(visibility)
if err != nil {
return nil, "", err
}
Comment thread cmd/wfctl/secrets.go
// dispatcher that reads plugin.json required_secrets[]. The
// env-name flow stays on runSecretsSetup.
for _, a := range args[1:] {
if a == "--plugin" || strings.HasPrefix(a, "--plugin=") {
Comment thread cmd/wfctl/secrets.go
Comment on lines +35 to +37
// `secrets setup --plugin <name>` shells out to a separate
// dispatcher that reads plugin.json required_secrets[]. The
// env-name flow stays on runSecretsSetup.
Comment on lines +95 to +100
// TestRunSecretsSetupPlugin_PiperReadsRequiredSecrets exercises the
// full flow with a piped reader for input. Output goes to a buffer.
//
// We swap out stdin via the io.Reader arg + verify the buffered out
// reports each secret as "set".
func TestRunSecretsSetupPlugin_PiperReadsRequiredSecrets(t *testing.T) {
@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

❌ Patch coverage is 40.98361% with 72 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cmd/wfctl/secrets_setup_plugin.go 42.01% 55 Missing and 14 partials ⚠️
cmd/wfctl/secrets.go 0.00% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

@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:314951: parsing iteration count: invalid syntax
baseline-bench.txt:611823: parsing iteration count: invalid syntax
baseline-bench.txt:912901: parsing iteration count: invalid syntax
baseline-bench.txt:1193021: parsing iteration count: invalid syntax
baseline-bench.txt:1497465: parsing iteration count: invalid syntax
benchmark-results.txt:274: parsing iteration count: invalid syntax
benchmark-results.txt:671390: parsing iteration count: invalid syntax
benchmark-results.txt:1382880: parsing iteration count: invalid syntax
benchmark-results.txt:1838674: parsing iteration count: invalid syntax
benchmark-results.txt:2265272: parsing iteration count: invalid syntax
benchmark-results.txt:2694948: 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 │
                            │       sec/op       │
InterpreterCreation-4               8.340m ± 62%
ComponentLoad-4                     3.622m ±  9%
ComponentExecute-4                  1.946µ ±  1%
PoolContention/workers-1-4          1.092µ ±  2%
PoolContention/workers-2-4          1.085µ ±  1%
PoolContention/workers-4-4          1.080µ ±  1%
PoolContention/workers-8-4          1.091µ ±  0%
PoolContention/workers-16-4         1.089µ ±  1%
ComponentLifecycle-4                3.572m ±  0%
SourceValidation-4                  2.338µ ±  1%
RegistryConcurrent-4                802.2n ±  4%
LoaderLoadFromString-4              3.591m ±  1%
geomean                             18.95µ

                            │ 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: AMD EPYC 9V74 80-Core Processor                
                            │ benchmark-results.txt │
                            │        sec/op         │
InterpreterCreation-4                 2.468m ± 244%
ComponentLoad-4                       2.741m ±   2%
ComponentExecute-4                    1.416µ ±   1%
PoolContention/workers-1-4            780.2n ±   2%
PoolContention/workers-2-4            776.8n ±   0%
PoolContention/workers-4-4            773.5n ±   2%
PoolContention/workers-8-4            775.1n ±   2%
PoolContention/workers-16-4           777.7n ±   1%
ComponentLifecycle-4                  2.716m ±   0%
SourceValidation-4                    1.627µ ±   4%
RegistryConcurrent-4                  589.8n ±   6%
LoaderLoadFromString-4                2.727m ±   1%
geomean                               12.79µ

                            │ 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 7763 64-Core Processor                
                                  │ baseline-bench.txt │
                                  │       sec/op       │
CircuitBreakerDetection-4                  287.9n ± 4%
CircuitBreakerExecution_Success-4          21.34n ± 1%
CircuitBreakerExecution_Failure-4          66.19n ± 2%
geomean                                    74.08n

                                  │ 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: AMD EPYC 9V74 80-Core Processor                
                                  │ benchmark-results.txt │
                                  │        sec/op         │
CircuitBreakerDetection-4                     231.3n ± 4%
CircuitBreakerExecution_Success-4             17.57n ± 0%
CircuitBreakerExecution_Failure-4             55.32n ± 0%
geomean                                       60.82n

                                  │ 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 7763 64-Core Processor                
                                 │ baseline-bench.txt │
                                 │       sec/op       │
IaCStateBackend_InProcess-4              307.8n ± 26%
IaCStateBackend_GRPC-4                   9.351m ±  5%
JQTransform_Simple-4                     666.7n ± 37%
JQTransform_ObjectConstruction-4         1.502µ ±  0%
JQTransform_ArraySelect-4                3.429µ ±  1%
JQTransform_Complex-4                    38.76µ ±  2%
JQTransform_Throughput-4                 1.842µ ±  0%
SSEPublishDelivery-4                     63.82n ±  7%
geomean                                  3.816µ

                                 │ baseline-bench.txt │
                                 │        B/op        │
IaCStateBackend_InProcess-4             416.0 ±  0%
IaCStateBackend_GRPC-4                5.735Mi ± 12%
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.840k ± 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: AMD EPYC 9V74 80-Core Processor                
                                 │ benchmark-results.txt │
                                 │        sec/op         │
IaCStateBackend_InProcess-4                 225.1n ± 29%
IaCStateBackend_GRPC-4                      8.094m ±  2%
JQTransform_Simple-4                        527.7n ± 17%
JQTransform_ObjectConstruction-4            1.107µ ±  1%
JQTransform_ArraySelect-4                   2.671µ ±  3%
JQTransform_Complex-4                       33.12µ ±  2%
JQTransform_Throughput-4                    1.375µ ±  1%
SSEPublishDelivery-4                        49.82n ±  1%
geomean                                     2.994µ

                                 │ benchmark-results.txt │
                                 │         B/op          │
IaCStateBackend_InProcess-4                416.0 ±  0%
IaCStateBackend_GRPC-4                   5.667Mi ± 12%
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.859k ± 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 7763 64-Core Processor                
                                    │ baseline-bench.txt │
                                    │       sec/op       │
SchemaValidation_Simple-4                   1.089µ ± 16%
SchemaValidation_AllFields-4                1.646µ ±  3%
SchemaValidation_FormatValidation-4         1.588µ ±  1%
SchemaValidation_ManySchemas-4              1.864µ ±  4%
geomean                                     1.518µ

                                    │ 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: AMD EPYC 9V74 80-Core Processor                
                                    │ benchmark-results.txt │
                                    │        sec/op         │
SchemaValidation_Simple-4                      845.7n ± 17%
SchemaValidation_AllFields-4                   1.272µ ±  1%
SchemaValidation_FormatValidation-4            1.212µ ±  1%
SchemaValidation_ManySchemas-4                 1.248µ ±  1%
geomean                                        1.130µ

                                    │ 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 7763 64-Core Processor                
                                   │ baseline-bench.txt │
                                   │       sec/op       │
EventStoreAppend_InMemory-4                1.294µ ± 12%
EventStoreAppend_SQLite-4                  1.321m ±  2%
GetTimeline_InMemory/events-10-4           13.65µ ±  3%
GetTimeline_InMemory/events-50-4           62.55µ ± 25%
GetTimeline_InMemory/events-100-4          125.2µ ±  1%
GetTimeline_InMemory/events-500-4          645.9µ ±  1%
GetTimeline_InMemory/events-1000-4         1.328m ±  1%
GetTimeline_SQLite/events-10-4             108.2µ ±  4%
GetTimeline_SQLite/events-50-4             253.9µ ±  0%
GetTimeline_SQLite/events-100-4            428.3µ ±  0%
GetTimeline_SQLite/events-500-4            1.831m ±  0%
GetTimeline_SQLite/events-1000-4           3.553m ±  3%
geomean                                    218.7µ

                                   │ baseline-bench.txt │
                                   │        B/op        │
EventStoreAppend_InMemory-4                  796.0 ± 6%
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.39Ki

                                   │ 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: AMD EPYC 9V74 80-Core Processor                
                                   │ benchmark-results.txt │
                                   │        sec/op         │
EventStoreAppend_InMemory-4                   738.8n ±  3%
EventStoreAppend_SQLite-4                     2.456m ± 71%
GetTimeline_InMemory/events-10-4              9.811µ ±  2%
GetTimeline_InMemory/events-50-4              54.24µ ±  3%
GetTimeline_InMemory/events-100-4             109.6µ ±  4%
GetTimeline_InMemory/events-500-4             476.4µ ± 18%
GetTimeline_InMemory/events-1000-4            885.9µ ±  1%
GetTimeline_SQLite/events-10-4                66.82µ ±  1%
GetTimeline_SQLite/events-50-4                173.3µ ±  1%
GetTimeline_SQLite/events-100-4               306.1µ ±  2%
GetTimeline_SQLite/events-500-4               1.318m ±  2%
GetTimeline_SQLite/events-1000-4              2.578m ±  3%
geomean                                       168.9µ

                                   │ benchmark-results.txt │
                                   │         B/op          │
EventStoreAppend_InMemory-4                     852.5 ± 3%
EventStoreAppend_SQLite-4                     1.982Ki ± 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.77Ki

                                   │ benchmark-results.txt │
                                   │       allocs/op       │
EventStoreAppend_InMemory-4                     7.000 ± 0%
EventStoreAppend_SQLite-4                       53.00 ± 2%
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
Copy link
Copy Markdown
Contributor Author

Superseded by the consolidated PR with lint fixes.

@intel352 intel352 closed this May 20, 2026
intel352 added a commit that referenced this pull request May 20, 2026
Supersedes #736 + #737 with lint fixes applied:

dyndns/ (T14..T16):
- IP-detect multi-source quorum + diff + Update callback +
  exp-backoff with jitter. 12 tests.

cmd/wfctl/secrets_setup_plugin.go (T3+T4):
- secrets setup --plugin reads plugin.json required_secrets[],
  prompts each (masked iff sensitive), writes to chosen GH scope
  (repo|env|org). 7 tests.

Lint fixes vs the original PRs:
- dyndns/dyndns.go Run() — replaced empty-branch (SA9003) with
  explicit `_ = d.Tick(...)` ignoring the error.
- dyndns/dyndns.go jitter — math/rand/v2 G404 false-positive
  silenced with nolint:gosec annotation (decorrelation, not
  crypto).
- dyndns/dyndns.go timeAfter — replaced unlambda wrapper with
  direct `var timeAfter = time.After`.
- cmd/wfctl/secrets.go — hoisted `args[1:]` into a local var
  to silence gosec G602 (already bounded by outer switch).

All tests pass; golangci-lint clean.

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.

2 participants