feat: add Red Hat media type profile for oc-mirror#6
Conversation
…d content Add Markdown (Marp-compatible) version of the OCI skill distribution deck. Update HTML deck with new slides on disconnected/air-gapped environments and multiple consumption paths based on OCPSTRAT-3122 Jira discussion. Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com> Signed-off-by: Pavel Anni <panni@redhat.com>
Add --media-type flag to skillctl pack that selects between standard OCI media types (default) and Red Hat-specific types needed for oc-mirror to identify skill artifacts in disconnected environments. Standard OCI types remain the default to preserve compatibility with all registries and tooling. The "redhat" profile sets layer and config media types to application/vnd.redhat.agentskill.* while keeping the manifest type standard so kubelet image volumes continue to work. Ref: OCPSTRAT-3122 Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com> Signed-off-by: Pavel Anni <panni@redhat.com>
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 46 minutes and 52 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughIntroduces OCI media type profile selection for skill image packing. Users can now specify Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Address code review findings: - Add ParseMediaTypeProfile() with whitespace trimming and case-insensitive matching, following the ParseState() pattern - Validate at CLI layer before reaching Pack() - Simplify resolveMediaTypes() to return only values (no error) since invalid profiles are caught at parse time - Add test cases for whitespace, mixed case, and error messages Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com> Signed-off-by: Pavel Anni <panni@redhat.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
pkg/oci/mediatype.go (1)
39-46: Preferocispecconstants over hardcoded strings for the standard profile.
pack.goimportsocispecwhich already exposesMediaTypeImageLayerGzipandMediaTypeImageConfig. Using them here keeps the standard-profile values in lockstep with the spec package and avoids drift.Proposed refactor
-func resolveMediaTypes(profile MediaTypeProfile) (layer, config string) { - switch profile { - case MediaTypeRedHat: - return RedHatMediaTypeSkillLayer, RedHatMediaTypeSkillConfig - default: - return "application/vnd.oci.image.layer.v1.tar+gzip", - "application/vnd.oci.image.config.v1+json" - } -} +func resolveMediaTypes(profile MediaTypeProfile) (layer, config string) { + switch profile { + case MediaTypeRedHat: + return RedHatMediaTypeSkillLayer, RedHatMediaTypeSkillConfig + default: + return ocispec.MediaTypeImageLayerGzip, ocispec.MediaTypeImageConfig + } +}Note:
mediatype_test.goalready asserts the literal strings, so no test change required if the literals match.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/oci/mediatype.go` around lines 39 - 46, The standard-profile branch in resolveMediaTypes uses hardcoded media-type strings; replace those literals with the ocispec constants (MediaTypeImageLayerGzip and MediaTypeImageConfig) so the default case returns ocispec.MediaTypeImageLayerGzip and ocispec.MediaTypeImageConfig instead of the raw strings; update the import usage if necessary to reference ocispec in the pkg/oci/mediatype.go file and keep the MediaTypeRedHat branch as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@pkg/oci/mediatype.go`:
- Around line 20-22: The RedHat media-type constant RedHatMediaTypeSkillLayer
conflicts with createLayer() in pkg/oci/pack.go because createLayer() always
produces a gzip-compressed tar; update createLayer() to branch on the RedHat
profile and skip gzip compression (producing plain tar) so the produced blob,
descriptor size, and diff_id match the uncompressed tar media type
RedHatMediaTypeSkillLayer, or alternatively change RedHatMediaTypeSkillLayer to
the gzip variant (application/vnd.redhat.agentskill.layer.v1+tar+gzip) if the
RedHat spec allows compressed layers; locate the branching logic in
createLayer(), adjust the compression step and the code that computes diff_id
and descriptor.Size accordingly, and ensure consistency between the media type
constant RedHatMediaTypeSkillLayer and the actual blob produced.
In `@pkg/oci/oci_test.go`:
- Around line 480-508: TestPackRedHatMediaType currently only checks the
manifest media type via client.Inspect and never verifies that the packed
manifest's config and layer entries use the Red Hat media types; update the test
to fetch the manifest bytes for the tagged ref returned by client.Pack/Inspect
(or extend InspectResult) and unmarshal into ocispec.Manifest, then assert that
m.Config.MediaType == oci.RedHatMediaTypeSkillConfig and m.Layers[0].MediaType
== oci.RedHatMediaTypeSkillLayer so the Red Hat profile is actually exercised
end-to-end; locate this logic around TestPackRedHatMediaType and the client.Pack
/ client.Inspect usage and either call the existing manifest fetch helper or add
one in the test to perform the manifest fetch and checks.
---
Nitpick comments:
In `@pkg/oci/mediatype.go`:
- Around line 39-46: The standard-profile branch in resolveMediaTypes uses
hardcoded media-type strings; replace those literals with the ocispec constants
(MediaTypeImageLayerGzip and MediaTypeImageConfig) so the default case returns
ocispec.MediaTypeImageLayerGzip and ocispec.MediaTypeImageConfig instead of the
raw strings; update the import usage if necessary to reference ocispec in the
pkg/oci/mediatype.go file and keep the MediaTypeRedHat branch as-is.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 0d320bb7-2c9e-47d9-b25e-e4b6bbe16368
📒 Files selected for processing (9)
.gitignoredocs/slides/oci-skill-distribution-deck.htmldocs/slides/oci-skill-distribution-deck.mdinternal/cli/pack.gopkg/oci/client.gopkg/oci/mediatype.gopkg/oci/mediatype_test.gopkg/oci/oci_test.gopkg/oci/pack.go
| RedHatMediaTypeSkillLayer = "application/vnd.redhat.agentskill.layer.v1+tar" | ||
| RedHatMediaTypeSkillConfig = "application/vnd.redhat.agentskill.config.v1+json" | ||
| ) |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Red Hat agent skill OCI media type application/vnd.redhat.agentskill.layer.v1+tar oc-mirror specification
💡 Result:
The media type "application/vnd.redhat.agentskill.layer.v1+tar" appears to be a custom OCI layer media type defined by Red Hat for packaging "agent skills" as OCI artifacts in container registries like Red Hat Quay. Agent skills are reusable instruction sets or capabilities for AI agents, following emerging standards like agentskills.io, packaged similarly to Helm charts or OPA policies. To use this media type in Red Hat Quay: - Enable general OCI support: FEATURE_GENERAL_OCI_SUPPORT: true - Add to ALLOWED_OCI_ARTIFACT_TYPES in config.yaml, e.g.: application/vnd.redhat.agentskill.config.v1+json: - application/vnd.redhat.agentskill.layer.v1+tar - Reconfigure Quay. oc-mirror, used for mirroring OpenShift images and operators to disconnected environments, supports standard OCI images and catalogs but has no explicit mention of agent skill media types or special handling. Agent skills would be mirrored as regular OCI artifacts if included in an ImageSetConfiguration. No official Red Hat documentation explicitly defines this exact media type as of 2026-04-21, suggesting it is either emerging (related to Red Hat AI/OpenShift agentic workflows) or for internal/experimental use in agent-mode operators. Similar patterns exist in Quay docs for custom OCI types like application/vnd.sylabs.sif.layer.v1+tar.
Citations:
- 1: https://docs.redhat.com/en/documentation/red_hat_quay/3.10/html/manage_red_hat_quay/supported-oci-media-types
- 2: https://docs.redhat.com/en/documentation/red_hat_quay/3.9/html/manage_red_hat_quay/supported-oci-media-types
- 3: https://docs.redhat.com/en/documentation/red_hat_quay/3.12/html/manage_red_hat_quay/supported-oci-media-types
- 4: https://github.com/ThomasVitale/agents-skills-oci-artifacts-spec
- 5: https://github.com/openshift/oc-mirror
- 6: https://docs.redhat.com/en/documentation/openshift_container_platform/4.15/html/installing_an_on-premise_cluster_with_the_agent-based_installer/understanding-disconnected-installation-mirroring
🏁 Script executed:
# First, find the createLayer function in pack.go
fd -t f "pack.go" | head -20Repository: redhat-et/skillimage
Length of output: 100
🏁 Script executed:
# Search for createLayer implementation
rg -A 30 "func.*createLayer" --type goRepository: redhat-et/skillimage
Length of output: 1277
🏁 Script executed:
# Check for any references to RedHatMediaTypeSkillLayer usage
rg "RedHatMediaTypeSkillLayer" --type goRepository: redhat-et/skillimage
Length of output: 315
🏁 Script executed:
# Look for OCPSTRAT-3122 references or specification files
rg "OCPSTRAT-3122|agentskill" --type go -iRepository: redhat-et/skillimage
Length of output: 265
🏁 Script executed:
# Check the mediatype.go file to see all media type definitions
cat -n pkg/oci/mediatype.go | head -50Repository: redhat-et/skillimage
Length of output: 1915
🏁 Script executed:
# Get the full createLayer function
rg -A 100 "^func createLayer" pkg/oci/pack.goRepository: redhat-et/skillimage
Length of output: 2529
🏁 Script executed:
# Also check what the function returns and how it's used
rg -B 5 -A 15 "createLayer(" pkg/oci/pack.go | head -80Repository: redhat-et/skillimage
Length of output: 138
🏁 Script executed:
# Check for any spec files or documentation about media types
fd -t f "spec|SPEC|spec.md|agentskill" | head -20Repository: redhat-et/skillimage
Length of output: 152
🏁 Script executed:
# Search for any comments or documentation about the +tar media type choice
rg "tar\+gzip|tar\+|media.*type" pkg/oci/pack.go -B 2 -A 2Repository: redhat-et/skillimage
Length of output: 191
🏁 Script executed:
# Check git history to see if there are related commits or TODOs
rg "TODO|FIXME|BUG|XXX" pkg/oci/ | grep -i "media\|tar\|gzip\|compress"Repository: redhat-et/skillimage
Length of output: 46
🏁 Script executed:
# Check if there's any special handling for the RedHat profile during layer creation
rg -B 10 -A 10 "resolveMediaTypes|MediaTypeProfile" pkg/oci/pack.goRepository: redhat-et/skillimage
Length of output: 790
🏁 Script executed:
# Read the implementation spec
cat docs/design/2026-04-16-implementation-spec.mdRepository: redhat-et/skillimage
Length of output: 10890
🏁 Script executed:
# Look for any other design docs or specifications
fd -t f "design|spec" docs/Repository: redhat-et/skillimage
Length of output: 234
🏁 Script executed:
# Search for OCPSTRAT or any references to Red Hat specifications
rg "OCPSTRAT|RHTAS|Red Hat|redhat" docs/ -iRepository: redhat-et/skillimage
Length of output: 50376
🏁 Script executed:
# Check if there's any comment in the code explaining the +tar choice
rg -B 5 "RedHatMediaTypeSkillLayer" pkg/oci/Repository: redhat-et/skillimage
Length of output: 1145
🏁 Script executed:
# Check if there's any TODO or FIXME related to gzip/compression in redhat profile
rg "TODO|FIXME|gzip|compress" pkg/oci/ -B 2 -A 2 | grep -A 3 -B 3 "redhat\|RedHat"Repository: redhat-et/skillimage
Length of output: 441
🏁 Script executed:
# Look for any spec or documentation files that might define the redhat media type behavior
find docs/ -type f -name "*.md" | xargs rg "tar\+gzip|tar\+|RedHat.*media|agentskill.*layer" -l 2>/dev/nullRepository: redhat-et/skillimage
Length of output: 152
🏁 Script executed:
# Check the slides for more context about the redhat media type
grep -A 10 -B 10 "application/vnd.redhat.agentskill.layer.v1" docs/slides/oci-skill-distribution-deck.mdRepository: redhat-et/skillimage
Length of output: 1101
🏁 Script executed:
# Check implementation spec for any notes about media type choices
grep -A 20 -B 5 "RedHat.*media\|+tar\|redhat.*profile" docs/design/2026-04-16-implementation-spec.md | head -60Repository: redhat-et/skillimage
Length of output: 46
Fix media type and content mismatch for RedHat profile.
pkg/oci/pack.go createLayer() produces a tar.gz layer regardless of profile, but RedHatMediaTypeSkillLayer declares application/vnd.redhat.agentskill.layer.v1+tar per OCPSTRAT-3122. Consumers (e.g., oc-mirror) expecting uncompressed tar will fail.
Branch createLayer() to skip gzip compression when the RedHat profile is selected, adjusting diff_id and descriptor sizes accordingly. Alternatively, if OCPSTRAT-3122 actually permits gzip, change the media type to application/vnd.redhat.agentskill.layer.v1+tar+gzip.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/oci/mediatype.go` around lines 20 - 22, The RedHat media-type constant
RedHatMediaTypeSkillLayer conflicts with createLayer() in pkg/oci/pack.go
because createLayer() always produces a gzip-compressed tar; update
createLayer() to branch on the RedHat profile and skip gzip compression
(producing plain tar) so the produced blob, descriptor size, and diff_id match
the uncompressed tar media type RedHatMediaTypeSkillLayer, or alternatively
change RedHatMediaTypeSkillLayer to the gzip variant
(application/vnd.redhat.agentskill.layer.v1+tar+gzip) if the RedHat spec allows
compressed layers; locate the branching logic in createLayer(), adjust the
compression step and the code that computes diff_id and descriptor.Size
accordingly, and ensure consistency between the media type constant
RedHatMediaTypeSkillLayer and the actual blob produced.
- Fix layer MIME type to match gzip-compressed content: change RedHatMediaTypeSkillLayer from +tar to .tar+gzip since createLayer() always produces gzip output - Add ConfigMediaType and LayerMediaType to InspectResult so callers can verify the inner descriptor types - Strengthen TestPackRedHatMediaType to assert config and layer media types end-to-end, not just the manifest type - Use ocispec constants instead of hardcoded strings in resolveMediaTypes Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com> Signed-off-by: Pavel Anni <panni@redhat.com>
Summary
--media-typeflag toskillctl packwith two profiles:standard(default) andredhatredhatprofile usesapplication/vnd.redhat.agentskill.layer.v1+tarandapplication/vnd.redhat.agentskill.config.v1+jsonmedia types, enablingoc-mirrorto identify skill artifacts for disconnected/air-gapped mirroringapplication/vnd.oci.image.manifest.v1+jsonin both profiles so kubelet image volumes and registry tooling work regardlessRef: OCPSTRAT-3122 (Agent skill packaging for OpenShift)
Test plan
TestResolveMediaTypes— covers standard, redhat, empty, and invalid profilesTestPackRedHatMediaType— full pack with redhat profile, verifies manifest type stays standardTestPackInvalidMediaType— rejects unknown profile namesmake lint— 0 issuesskillctl pack --media-type redhat examples/skills/resume-screenerand inspect the OCI layout to verify layer/config media types🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
--media-typeCLI flag to select media type profiles (standard or Red Hat) when packing skills.Documentation
Tests