posit-dev / posit-dev/images-shared
Publish from the retained SOCI OCI layout instead of re-downloading from the temp registry
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 2
- Forks
- 0
- Avg merge
- 4d 13h
- Merged PRs (30d)
- 22
Description
Problem
The publish stage moves the full image over the network six times per SOCI-enabled target. Three of those are avoidable.
SociConvertWorkflow (posit_bakery/plugins/builtin/imagetools/soci.py:193-248) pulls every layer into a local OCI layout, converts it, pushes every layer back to the temp registry, then deletes the scratch directory in an unconditional finally:. OrasIndexCopyWorkflow then issues one oras cp per destination registry — and each one re-downloads from the temp registry, because ORAS keeps no content store between invocations.
The local layout holding every byte is discarded immediately before two copies re-download the same bytes.
| Step | Today | Publishing from the retained layout |
|---|---|---|
oras manifest index create |
metadata | metadata |
SOCI pull --to-oci-layout |
1 down | 1 down |
SOCI push --from-oci-layout → temp |
1 up | eliminated |
| scratch deleted | — | src deleted, out retained |
oras cp temp → Docker Hub |
1 down + 1 up | 1 up from layout |
oras cp temp → GHCR |
1 down + 1 up | 1 up from layout |
| Total | 3 down + 3 up = 6× | 1 down + 2 up = 3× |
Marginal cost per additional destination registry also halves: 2× → 1×.
SOCI is enabled on every image using this path — all three in images-connect, all three in images-workbench, and package-manager.
Validated
Against oras 1.3.3 with two local registries (one would dedup blobs and mask the effect):
oras cp --from-oci-layout <layout>@<digest> <registry>/<repo>:t1,t2,t3succeeds; all three tags resolve to the same digest. The multi-tag destination formOrasIndexCopyWorkflowbuilds (oras.py:268) works from a layout source.- Counting blob GETs against the source registry, two sequential registry→registry copies fetched blobs both times (2 and 2). The 6× figure is measured, not assumed.
Risks to weigh
Peak disk under parallel stage 1 — the blocking one. _run_publish_stage1 is fanned out across a ParallelShellExecutor (imagetools.py:644), while stage 2 is deliberately kept ordered for Docker Hub tag display (commit 5c4882b3, #484, #759). Retained layouts must survive that parallel→ordered boundary, so all concurrent targets' layouts coexist instead of each being freed at the end of its own conversion.
Fusing stage 1 and stage 2 per target is not available — it would break the ordered push. Mitigations: delete src immediately after conversion (halves per-target peak, since src and out currently coexist), cap --jobs, or accept and document a ceiling.
Losing the temp -soci artifact removes a retry checkpoint. Today a failed destination copy retries straight from the temp registry. Without the push-back, failure after conversion means redoing pull and an expensive SOCI conversion.
A middle option worth considering first: keep the push-back and publish from the retained layout — 1 down + 1 up + 2 up = 4×. Still a third off today, preserves the checkpoint, changes less.
Push ordering. The layout push is by digest (f"{out_layout}@{digest}"); today's copies start from a tagged temp ref. Equivalence needs confirming against #484's reverse-order requirement.
Interaction with #755. Splitting jobs per OS and architecture increases target count, so more layouts coexist and the disk risk worsens — though each is smaller.
Scope
Publish leg only. Cache import, cache export, and PR builds are unaffected.
Related
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Trace SociConvertWorkflow in posit_bakery/plugins/builtin/imagetools/soci.py:193-248, OrasIndexCopyWorkflow in oras.py:268, and _run_publish_stage1 in imagetools.py:644. First map the parallel stage-1 to ordered stage-2 lifecycle, then choose and validate a retained-layout strategy that accounts for disk usage, retry behavior, digest-based ordering, and the measured reduction in registry transfers.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devops, performance, release
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100