Skip to content

feat: add step.secret_fetch pipeline step for tenant-aware secret resolution#318

Merged
intel352 merged 4 commits intomainfrom
copilot/add-step-secret-fetch
Mar 12, 2026
Merged

feat: add step.secret_fetch pipeline step for tenant-aware secret resolution#318
intel352 merged 4 commits intomainfrom
copilot/add-step-secret-fetch

Conversation

Copy link
Contributor

Copilot AI commented Mar 12, 2026

secrets.aws and secrets.vault modules expose a SecretProvider service but no pipeline step consumes it, making them unusable from declarative YAML configs. This adds step.secret_fetch to bridge that gap.

Changes

  • module/pipeline_step_secret_fetch.go — New step with a SecretFetchProvider interface (satisfied by both SecretsAWSModule and SecretsVaultModule). Secret IDs/ARNs are Go template expressions resolved against the live PipelineContext, enabling per-tenant dynamic ARN construction from trigger data or upstream step outputs.
  • module/pipeline_step_secret_fetch_test.go — 12 unit tests covering factory validation, single/multi-secret fetch, tenant-aware dynamic resolution (from trigger data and from previous step output), and error paths.
  • plugins/pipelinesteps/plugin.go — Registers step.secret_fetch in both the manifest StepTypes list and StepFactories().
  • DOCUMENTATION.md — Config reference and YAML examples.

Usage

ARNs are resolved per-request against the pipeline context — tenant ID from trigger data, or ARNs returned by a preceding DB lookup step:

steps:
  - name: lookup_integration
    type: step.db_query
    config:
      query: "SELECT * FROM integrations WHERE tenant_id = $1"
      params: ["{{.tenant_id}}"]

  - name: fetch_creds
    type: step.secret_fetch
    config:
      module: aws-secrets          # name of the secrets.aws module instance
      secrets:
        token_url:     "{{.steps.lookup_integration.row.token_url_arn}}"
        client_id:     "{{.steps.lookup_integration.row.client_id_arn}}"
        client_secret: "{{.steps.lookup_integration.row.client_secret_arn}}"

  - name: call_api
    type: step.http_call
    config:
      url: "https://login.example.com/oauth/token"
      method: POST
      oauth2:
        token_url:     "{{.steps.fetch_creds.token_url}}"
        client_id:     "{{.steps.fetch_creds.client_id}}"
        client_secret: "{{.steps.fetch_creds.client_secret}}"

Outputs one field per key in secrets, plus fetched: true.

Original prompt

This section details on the original issue you should resolve

<issue_title>Feature: step.secret_fetch to resolve secrets from secrets.aws module in pipelines</issue_title>
<issue_description>## Summary

The secrets.aws module provides a SecretProvider service backed by AWS Secrets Manager, but there is no pipeline step type to fetch secrets at runtime. Pipelines that need credentials (e.g., OAuth tokens for external API calls) cannot resolve secrets from the module.

Use Case

An event-triggered pipeline processes form submissions and needs to call the Salesforce API with per-affiliate OAuth credentials stored in AWS Secrets Manager:

steps:
  - name: fetch_creds
    type: step.secret_fetch
    config:
      module: aws-secrets          # secrets.aws module name
      secret_id: "{{.steps.lookup_integration.row.provider_config.client_secret_arn}}"
      # Or multiple secrets at once:
      secrets:
        token_url: "{{.steps.lookup_integration.row.provider_config.token_url_secret}}"
        client_id: "{{.steps.lookup_integration.row.provider_config.client_id_secret}}"
        client_secret: "{{.steps.lookup_integration.row.provider_config.client_secret_secret}}"

  - name: call_salesforce
    type: step.http_call
    config:
      url: "https://login.salesforce.com/services/oauth2/token"
      method: POST
      auth:
        type: oauth2_client_credentials
        token_url: "{{.steps.fetch_creds.token_url}}"
        client_id: "{{.steps.fetch_creds.client_id}}"
        client_secret: "{{.steps.fetch_creds.client_secret}}"

Current State

  • secrets.aws module: exists, outputs a SecretProvider service
  • secrets.vault module: exists, same pattern
  • No step type consumes the SecretProvider to fetch secrets into the pipeline context

Proposed Step

- name: fetch_creds
  type: step.secret_fetch
  config:
    module: aws-secrets        # Name of a secrets.* module
    secrets:                   # Map of output keys → secret IDs/ARNs
      my_key: "arn:aws:secretsmanager:us-east-1:123:secret:my-secret"
    cache_ttl: "5m"            # Optional: cache resolved values to reduce API calls

Outputs:

  • Each key from the secrets map, with the resolved secret value
  • fetched: true/false

The step should:

  1. Resolve the SecretProvider from the named module
  2. Fetch each secret by ID/ARN
  3. Store resolved values in the pipeline context under the step's output namespace
  4. Optionally cache values for the configured TTL

Alternatives

  • Template-level secret resolution: {{secret "aws-secrets" "arn:..."}} as a template function. More ergonomic but harder to cache and error-handle.
  • Inline in step.http_call auth config: Teach the auth config to resolve secrets directly. Too tightly coupled.

Priority

This blocks using secrets.aws in any pipeline. Without it, the module exists but is unusable from declarative YAML configs.</issue_description>

<agent_instructions>Ensure there's a process to be able to fetch secrets in a tenant-aware fashion (multiple tenants in same application). As such the secret name or ARN or whatever is used should support dynamic evaluation to support the tenants</agent_instructions>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…olution

Implements a new pipeline step type that fetches secrets from secrets.aws
or secrets.vault modules at runtime. Secret IDs/ARNs support Go template
expressions evaluated against the live pipeline context, enabling
per-tenant dynamic secret resolution.

Changes:
- module/pipeline_step_secret_fetch.go: SecretFetchProvider interface,
  SecretFetchStep, NewSecretFetchStepFactory
- module/pipeline_step_secret_fetch_test.go: 12 tests covering factory
  validation, single/multi fetch, dynamic/tenant-aware resolution,
  error handling
- plugins/pipelinesteps/plugin.go: register step.secret_fetch
- plugins/pipelinesteps/plugin_test.go: update expected step count
- DOCUMENTATION.md: table entry + detailed section with examples

Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Copilot AI changed the title [WIP] Add step.secret_fetch to resolve secrets from secrets.aws module feat: add step.secret_fetch pipeline step for tenant-aware secret resolution Mar 12, 2026
Copilot AI requested a review from intel352 March 12, 2026 19:35
@intel352 intel352 marked this pull request as ready for review March 12, 2026 19:54
Copilot AI review requested due to automatic review settings March 12, 2026 19:54
Copy link
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 step.secret_fetch pipeline step so YAML-configured pipelines can fetch secrets at runtime from secrets.aws / secrets.vault, with secret IDs/ARNs dynamically template-resolved against the live PipelineContext for tenant-aware behavior.

Changes:

  • Introduces module.SecretFetchStep + factory to resolve templated secret IDs/ARNs and fetch them from a named secrets module service.
  • Registers step.secret_fetch in the pipelinesteps plugin manifest and factory registry.
  • Adds unit tests and documentation reference/examples for the new step.

Reviewed changes

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

Show a summary per file
File Description
module/pipeline_step_secret_fetch.go Implements step.secret_fetch (template resolution + service lookup + fetching).
module/pipeline_step_secret_fetch_test.go Adds unit tests for validation, dynamic resolution, and error paths.
plugins/pipelinesteps/plugin.go Registers the new step type in manifest + StepFactories().
plugins/pipelinesteps/plugin_test.go Updates expected step factory list to include step.secret_fetch.
DOCUMENTATION.md Documents step.secret_fetch configuration, outputs, and examples.
plugins/all/all.go Import formatting adjustment.
modernize/manifest_rule_test.go Formatting adjustment.
mcp/server.go Formatting adjustment.

Comment on lines +42 to +54
raw, _ := config["secrets"].(map[string]any)
if len(raw) == 0 {
return nil, fmt.Errorf("secret_fetch step %q: 'secrets' map is required and must not be empty", name)
}

secretMap := make(map[string]string, len(raw))
for k, v := range raw {
idStr, ok := v.(string)
if !ok {
return nil, fmt.Errorf("secret_fetch step %q: secrets[%q] must be a string (secret ID or ARN)", name, k)
}
secretMap[k] = idStr
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

The secrets map allows an output key of "fetched", but Execute() always writes output["fetched"] = true at the end, which will silently overwrite any fetched secret under that key. Consider rejecting "fetched" as a secrets-map key (and/or renaming the status field) during factory validation so outputs are deterministic.

Copilot uses AI. Check for mistakes.
Comment on lines +47 to +54
secretMap := make(map[string]string, len(raw))
for k, v := range raw {
idStr, ok := v.(string)
if !ok {
return nil, fmt.Errorf("secret_fetch step %q: secrets[%q] must be a string (secret ID or ARN)", name, k)
}
secretMap[k] = idStr
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

Factory validation accepts empty secret IDs/ARNs (e.g., secrets: {token: ""}) because it only type-checks to string. Since secret IDs are required inputs, validate non-empty/whitespace-only values up front to avoid executing provider.Get with an invalid key.

Copilot uses AI. Check for mistakes.
Comment on lines +84 to +96
for outputKey, idTemplate := range s.secrets {
// Resolve the secret ID/ARN template against the current pipeline context.
// This enables tenant-aware ARNs such as:
// "arn:aws:secretsmanager:us-east-1:123:secret:{{.tenant_id}}-creds"
resolvedID, resolveErr := s.tmpl.Resolve(idTemplate, pc)
if resolveErr != nil {
return nil, fmt.Errorf("secret_fetch step %q: failed to resolve secret ID for %q: %w", s.name, outputKey, resolveErr)
}

value, fetchErr := provider.Get(ctx, resolvedID)
if fetchErr != nil {
return nil, fmt.Errorf("secret_fetch step %q: failed to fetch secret %q (id=%q): %w", s.name, outputKey, resolvedID, fetchErr)
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

After resolving the secret ID/ARN template, resolvedID can be an empty string (TemplateEngine uses missingkey=zero). Add a guard to treat an empty resolved ID as an error before calling provider.Get, so misconfigured tenant-aware templates fail fast and don’t accidentally query an unexpected key.

Copilot uses AI. Check for mistakes.
@intel352
Copy link
Contributor

@copilot apply changes based on the comments in this thread

- Reject "fetched" as a secrets-map key (reserved for output status)
- Validate non-empty/non-whitespace secret IDs at factory time
- Guard against empty resolved IDs after template evaluation
- Add tests for all three new validation paths

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

Copilot AI commented Mar 12, 2026

@copilot apply changes based on the comments in this thread

Applied all three review suggestions in dad69d6:

  1. Reserved "fetched" key — factory now returns an error if "fetched" is used as a secrets-map key, since it is reserved for the output status field.
  2. Empty secret IDs at factory time — factory rejects empty or whitespace-only string values in the secrets map.
  3. Empty resolved ID at execute time — after template evaluation, an empty/whitespace-only resolved ID fast-fails with a descriptive error that includes the original template expression for easier debugging.

Added tests for all three paths (16 total, all passing).

@github-actions
Copy link

github-actions bot commented Mar 12, 2026

⏱ Benchmark Results

No significant performance regressions detected.

benchstat comparison (baseline → PR)
## benchstat: baseline → PR
baseline-bench.txt:244: parsing iteration count: invalid syntax
baseline-bench.txt:318245: parsing iteration count: invalid syntax
baseline-bench.txt:638781: parsing iteration count: invalid syntax
baseline-bench.txt:957973: parsing iteration count: invalid syntax
baseline-bench.txt:1244336: parsing iteration count: invalid syntax
baseline-bench.txt:1544214: parsing iteration count: invalid syntax
benchmark-results.txt:244: parsing iteration count: invalid syntax
benchmark-results.txt:313334: parsing iteration count: invalid syntax
benchmark-results.txt:609942: parsing iteration count: invalid syntax
benchmark-results.txt:871744: parsing iteration count: invalid syntax
benchmark-results.txt:1174649: parsing iteration count: invalid syntax
benchmark-results.txt:1491333: 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               6.777m ± 55%   6.310m ± 62%       ~ (p=0.589 n=6)
ComponentLoad-4                     3.569m ±  6%   3.481m ±  1%  -2.46% (p=0.002 n=6)
ComponentExecute-4                  2.029µ ±  2%   2.029µ ±  2%       ~ (p=0.619 n=6)
PoolContention/workers-1-4          1.112µ ±  1%   1.095µ ±  4%       ~ (p=0.394 n=6)
PoolContention/workers-2-4          1.095µ ±  1%   1.115µ ±  2%       ~ (p=0.065 n=6)
PoolContention/workers-4-4          1.099µ ±  3%   1.116µ ±  2%  +1.50% (p=0.037 n=6)
PoolContention/workers-8-4          1.104µ ±  3%   1.105µ ±  1%       ~ (p=0.853 n=6)
PoolContention/workers-16-4         1.135µ ±  3%   1.111µ ±  3%       ~ (p=0.240 n=6)
ComponentLifecycle-4                3.697m ±  1%   3.595m ±  1%  -2.75% (p=0.002 n=6)
SourceValidation-4                  2.442µ ±  1%   2.411µ ±  1%  -1.27% (p=0.045 n=6)
RegistryConcurrent-4                862.2n ±  2%   815.1n ±  2%  -5.46% (p=0.002 n=6)
LoaderLoadFromString-4              3.740m ±  1%   3.664m ±  2%  -2.02% (p=0.041 n=6)
geomean                             19.12µ         18.78µ        -1.79%

                            │ baseline-bench.txt │        benchmark-results.txt         │
                            │        B/op        │     B/op      vs base                │
InterpreterCreation-4               1.944Mi ± 0%   1.944Mi ± 0%       ~ (p=0.457 n=6)
ComponentLoad-4                     2.097Mi ± 0%   2.097Mi ± 0%       ~ (p=0.981 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.099Mi ± 0%   2.099Mi ± 0%       ~ (p=0.788 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.099Mi ± 0%   2.099Mi ± 0%       ~ (p=0.372 n=6)
geomean                             15.05Ki        15.05Ki       -0.00%
¹ all samples are equal

                            │ baseline-bench.txt │        benchmark-results.txt        │
                            │     allocs/op      │  allocs/op   vs base                │
InterpreterCreation-4                15.09k ± 0%   15.09k ± 0%       ~ (p=1.000 n=6)
ComponentLoad-4                      17.43k ± 0%   17.43k ± 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                 17.48k ± 0%   17.48k ± 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               17.47k ± 0%   17.47k ± 0%       ~ (p=1.000 n=6) ¹
geomean                               181.2         181.2       +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                  292.2n ± 3%   294.3n ± 15%       ~ (p=0.894 n=6)
CircuitBreakerExecution_Success-4          22.54n ± 1%   22.49n ±  0%  -0.20% (p=0.006 n=6)
CircuitBreakerExecution_Failure-4          64.40n ± 0%   65.32n ±  0%  +1.43% (p=0.002 n=6)
geomean                                    75.13n        75.62n        +0.64%

                                  │ 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                     896.5n ± 28%   899.5n ± 26%       ~ (p=0.589 n=6)
JQTransform_ObjectConstruction-4         1.473µ ± 26%   1.460µ ±  2%       ~ (p=0.102 n=6)
JQTransform_ArraySelect-4                3.364µ ±  1%   3.329µ ±  1%       ~ (p=0.065 n=6)
JQTransform_Complex-4                    38.50µ ±  1%   38.24µ ±  2%       ~ (p=0.093 n=6)
JQTransform_Throughput-4                 1.803µ ±  1%   1.790µ ±  0%  -0.75% (p=0.006 n=6)
SSEPublishDelivery-4                     62.60n ±  0%   65.97n ±  1%  +5.37% (p=0.002 n=6)
geomean                                  1.638µ         1.644µ        +0.37%

                                 │ 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.121µ ± 6%   1.118µ ± 3%       ~ (p=0.851 n=6)
SchemaValidation_AllFields-4                 1.689µ ± 7%   1.677µ ± 5%       ~ (p=0.669 n=6)
SchemaValidation_FormatValidation-4          1.594µ ± 2%   1.602µ ± 3%       ~ (p=0.197 n=6)
SchemaValidation_ManySchemas-4               1.813µ ± 2%   1.825µ ± 2%       ~ (p=0.981 n=6)
geomean                                      1.529µ        1.530µ       +0.06%

                                    │ 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.326µ ± 17%   1.284µ ± 15%       ~ (p=0.589 n=6)
EventStoreAppend_SQLite-4                  1.337m ±  3%   1.285m ±  5%  -3.93% (p=0.026 n=6)
GetTimeline_InMemory/events-10-4           14.33µ ±  5%   14.43µ ±  5%       ~ (p=1.000 n=6)
GetTimeline_InMemory/events-50-4           78.96µ ± 19%   79.28µ ± 22%       ~ (p=0.699 n=6)
GetTimeline_InMemory/events-100-4          128.8µ ±  1%   124.2µ ±  0%  -3.56% (p=0.002 n=6)
GetTimeline_InMemory/events-500-4          663.5µ ±  1%   641.9µ ±  1%  -3.26% (p=0.002 n=6)
GetTimeline_InMemory/events-1000-4         1.361m ±  1%   1.312m ±  1%  -3.59% (p=0.002 n=6)
GetTimeline_SQLite/events-10-4             119.0µ ±  1%   110.8µ ±  1%  -6.94% (p=0.002 n=6)
GetTimeline_SQLite/events-50-4             266.2µ ±  1%   257.4µ ±  2%  -3.33% (p=0.002 n=6)
GetTimeline_SQLite/events-100-4            438.2µ ±  1%   426.9µ ±  1%  -2.59% (p=0.002 n=6)
GetTimeline_SQLite/events-500-4            1.839m ±  1%   1.824m ±  1%       ~ (p=0.065 n=6)
GetTimeline_SQLite/events-1000-4           3.626m ±  2%   3.636m ±  3%       ~ (p=0.818 n=6)
geomean                                    229.7µ         224.0µ        -2.50%

                                   │ baseline-bench.txt │        benchmark-results.txt         │
                                   │        B/op        │     B/op      vs base                │
EventStoreAppend_InMemory-4                  779.0 ± 8%     786.0 ± 8%       ~ (p=0.859 n=6)
EventStoreAppend_SQLite-4                  1.983Ki ± 3%   1.982Ki ± 1%       ~ (p=0.827 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.242 n=6)
GetTimeline_InMemory/events-1000-4         944.3Ki ± 0%   944.3Ki ± 0%       ~ (p=0.602 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.727 n=6)
GetTimeline_SQLite/events-1000-4           1.639Mi ± 0%   1.639Mi ± 0%       ~ (p=0.567 n=6)
geomean                                    67.26Ki        67.31Ki       +0.07%
¹ 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.

@intel352
Copy link
Contributor

@copilot failing tests still

TestKnownStepTypesCoverAllPlugins was failing because step.secret_fetch
was registered in the pipelinesteps plugin but missing from the
KnownStepTypes() registry used by wfctl.

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

Copilot AI commented Mar 12, 2026

@copilot failing tests still

Fixed in 068cb39. TestKnownStepTypesCoverAllPlugins was failing because step.secret_fetch was registered in the pipelinesteps plugin but missing from KnownStepTypes() in cmd/wfctl/type_registry.go. Added the entry there.

@intel352 intel352 merged commit 2150d0c into main Mar 12, 2026
11 checks passed
@intel352 intel352 deleted the copilot/add-step-secret-fetch branch March 12, 2026 22:03
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.

Feature: step.secret_fetch to resolve secrets from secrets.aws module in pipelines

3 participants