Skip to content

docs: track native image-registry retention as wfctl infra follow-up#412

Merged
intel352 merged 1 commit into
mainfrom
docs/infra-retention-followup
Apr 18, 2026
Merged

docs: track native image-registry retention as wfctl infra follow-up#412
intel352 merged 1 commit into
mainfrom
docs/infra-retention-followup

Conversation

@intel352
Copy link
Copy Markdown
Contributor

Summary

BMW (#117), workflow-dnd (#10), and core-dump (upcoming) each ship a per-repo `.github/workflows/registry-retention.yml` that calls `doctl registry garbage-collection start` + tag-pruning bash + `actions/delete-package-versions@v5` for GHCR. That logic is duplicated across every consumer and re-implemented per cloud provider.

Adds one bullet to the out-of-scope follow-ups section of `docs/plans/2026-04-17-deploy-pipeline-multi-env-design.md` noting the engine work needed to lift retention into `wfctl infra`:

  • `infra.registry` module schema gains `retention_policy` with `keep_latest`, `untagged_ttl`, `schedule`
  • `wfctl infra gc` or scheduled `step.registry_gc` calls provider-native GC (DO / ECR / GCR / ACR) plus tag pruning
  • Consumers drop the workflow-file retention and declare retention in `infra.yaml`

Pure tracking doc change — no code affected.

Test plan

  • Diff is additive (one bullet, no edits elsewhere)
  • No code changes

🤖 Generated with Claude Code

BMW, workflow-dnd, and core-dump each ship a per-repo
.github/workflows/registry-retention.yml that calls
doctl registry garbage-collection start + tag-pruning bash +
actions/delete-package-versions@v5 for GHCR. That logic should live in
wfctl infra so downstream consumers declare retention in infra.yaml
instead of maintaining duplicate workflows.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 18, 2026 18:16
@intel352 intel352 merged commit 93425cc into main Apr 18, 2026
10 checks passed
@intel352 intel352 deleted the docs/infra-retention-followup branch April 18, 2026 18:16
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

Tracks a follow-up item for lifting container image registry retention/garbage-collection into wfctl infra, so downstream repos can declare provider-agnostic retention policies in infra.yaml instead of maintaining duplicated GitHub Actions workflows.

Changes:

  • Adds an out-of-scope follow-up bullet describing desired infra.registry retention policy fields and potential wfctl infra gc / step.registry_gc integration.

- Full prod in DND.
- Approval-gated promotion pattern docs and example.
- GHCR publish removal in BMW (post two clean prod deploys).
- **Native image-registry retention in `wfctl infra`.** Downstream consumers (buymywishlist, workflow-dnd, core-dump) currently run per-repo `.github/workflows/registry-retention.yml` workflows that call `doctl registry garbage-collection start` + tag-pruning bash + `actions/delete-package-versions@v5` for GHCR. This logic is duplicated across every consumer repo and re-implemented per provider. Engine work: add retention fields to `infra.registry` module schema (`retention_policy: { keep_latest: 20, untagged_ttl: 168h, schedule: "0 7 * * 0" }`), wire `wfctl infra gc` or a scheduled `step.registry_gc` that calls the provider-native GC endpoint (DO, ECR, GCR, ACR) plus tag pruning based on `keep_latest`. Downstream consumers then drop their retention workflow and declare retention in `infra.yaml`. DO's `doctl registry garbage-collection start --force --include-untagged-manifests` maps cleanly; ECR has lifecycle policies (JSON); GCR has retention policies (JSON). Schema should be provider-agnostic and delegate to plugin.
@github-actions
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:335430: parsing iteration count: invalid syntax
baseline-bench.txt:659461: parsing iteration count: invalid syntax
baseline-bench.txt:994139: parsing iteration count: invalid syntax
baseline-bench.txt:1312095: parsing iteration count: invalid syntax
baseline-bench.txt:1592809: parsing iteration count: invalid syntax
benchmark-results.txt:245: parsing iteration count: invalid syntax
benchmark-results.txt:325173: parsing iteration count: invalid syntax
benchmark-results.txt:693754: parsing iteration count: invalid syntax
benchmark-results.txt:998276: parsing iteration count: invalid syntax
benchmark-results.txt:1336602: parsing iteration count: invalid syntax
benchmark-results.txt:1658218: 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.113m ± 200%
ComponentLoad-4                       3.584m ±  14%
ComponentExecute-4                    1.933µ ±   8%
PoolContention/workers-1-4            1.086µ ±   4%
PoolContention/workers-2-4            1.087µ ±   1%
PoolContention/workers-4-4            1.091µ ±   1%
PoolContention/workers-8-4            1.088µ ±   1%
PoolContention/workers-16-4           1.093µ ±   3%
ComponentLifecycle-4                  3.601m ±   0%
SourceValidation-4                    2.262µ ±   1%
RegistryConcurrent-4                  795.5n ±   2%
LoaderLoadFromString-4                3.617m ±   2%
geomean                               17.41µ

                            │ 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.967m ± 166%
ComponentLoad-4                    3.489m ±  15%
ComponentExecute-4                 1.815µ ±   1%
PoolContention/workers-1-4         1.019µ ±   1%
PoolContention/workers-2-4         1.020µ ±   4%
PoolContention/workers-4-4         1.016µ ±   2%
PoolContention/workers-8-4         1.014µ ±   2%
PoolContention/workers-16-4        1.014µ ±   2%
ComponentLifecycle-4               3.498m ±   1%
SourceValidation-4                 2.068µ ±   0%
RegistryConcurrent-4               741.0n ±   4%
LoaderLoadFromString-4             3.540m ±   1%
geomean                            16.43µ

                            │ 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                     285.2n ± 5%
CircuitBreakerExecution_Success-4             21.50n ± 0%
CircuitBreakerExecution_Failure-4             66.16n ± 0%
geomean                                       74.02n

                                  │ 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                  296.7n ± 7%
CircuitBreakerExecution_Success-4          22.68n ± 0%
CircuitBreakerExecution_Failure-4          70.94n ± 0%
geomean                                    78.15n

                                  │ 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                        947.2n ± 16%
JQTransform_ObjectConstruction-4            1.425µ ±  0%
JQTransform_ArraySelect-4                   3.293µ ±  0%
JQTransform_Complex-4                       38.21µ ±  2%
JQTransform_Throughput-4                    1.760µ ±  1%
SSEPublishDelivery-4                        74.11n ±  1%
geomean                                     1.676µ

                                 │ 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                     816.6n ± 25%
JQTransform_ObjectConstruction-4         1.389µ ±  1%
JQTransform_ArraySelect-4                3.325µ ±  1%
JQTransform_Complex-4                    40.97µ ±  1%
JQTransform_Throughput-4                 1.725µ ±  2%
SSEPublishDelivery-4                     62.85n ±  0%
geomean                                  1.600µ

                                 │ 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µ ± 4%
SchemaValidation_AllFields-4                    1.695µ ± 3%
SchemaValidation_FormatValidation-4             1.603µ ± 1%
SchemaValidation_ManySchemas-4                  1.812µ ± 1%
geomean                                         1.529µ

                                    │ 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.077µ ± 7%
SchemaValidation_AllFields-4                 1.620µ ± 1%
SchemaValidation_FormatValidation-4          1.563µ ± 1%
SchemaValidation_ManySchemas-4               1.607µ ± 4%
geomean                                      1.446µ

                                    │ 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.175µ ± 23%
EventStoreAppend_SQLite-4                     1.322m ± 11%
GetTimeline_InMemory/events-10-4              13.61µ ±  3%
GetTimeline_InMemory/events-50-4              75.19µ ±  4%
GetTimeline_InMemory/events-100-4             120.3µ ±  7%
GetTimeline_InMemory/events-500-4             615.7µ ±  1%
GetTimeline_InMemory/events-1000-4            1.258m ±  1%
GetTimeline_SQLite/events-10-4                105.5µ ±  0%
GetTimeline_SQLite/events-50-4                244.8µ ±  1%
GetTimeline_SQLite/events-100-4               415.9µ ±  2%
GetTimeline_SQLite/events-500-4               1.755m ±  0%
GetTimeline_SQLite/events-1000-4              3.422m ±  0%
geomean                                       214.6µ

                                   │ benchmark-results.txt │
                                   │         B/op          │
EventStoreAppend_InMemory-4                     797.5 ± 6%
EventStoreAppend_SQLite-4                     1.983Ki ± 3%
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

                                   │ 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.058µ ±  9%
EventStoreAppend_SQLite-4                  1.001m ±  1%
GetTimeline_InMemory/events-10-4           12.36µ ±  1%
GetTimeline_InMemory/events-50-4           69.21µ ± 23%
GetTimeline_InMemory/events-100-4          106.1µ ±  3%
GetTimeline_InMemory/events-500-4          544.4µ ±  1%
GetTimeline_InMemory/events-1000-4         1.111m ±  1%
GetTimeline_SQLite/events-10-4             84.02µ ±  1%
GetTimeline_SQLite/events-50-4             222.1µ ±  0%
GetTimeline_SQLite/events-100-4            388.6µ ±  2%
GetTimeline_SQLite/events-500-4            1.699m ±  1%
GetTimeline_SQLite/events-1000-4           3.325m ±  2%
geomean                                    191.2µ

                                   │ baseline-bench.txt │
                                   │        B/op        │
EventStoreAppend_InMemory-4                  775.0 ± 6%
EventStoreAppend_SQLite-4                  1.984Ki ± 2%
GetTimeline_InMemory/events-10-4           7.953Ki ± 0%
GetTimeline_InMemory/events-50-4           46.62Ki ± 0%
GetTimeline_InMemory/events-100-4          94.48Ki ± 0%
GetTimeline_InMemory/events-500-4          472.8Ki ± 0%
GetTimeline_InMemory/events-1000-4         944.3Ki ± 0%
GetTimeline_SQLite/events-10-4             16.74Ki ± 0%
GetTimeline_SQLite/events-50-4             87.14Ki ± 0%
GetTimeline_SQLite/events-100-4            175.4Ki ± 0%
GetTimeline_SQLite/events-500-4            846.1Ki ± 0%
GetTimeline_SQLite/events-1000-4           1.639Mi ± 0%
geomean                                    67.24Ki

                                   │ 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