Create Component Versions

Component versions bundle your software artifacts with metadata, making them portable and verifiable. This guide walks you through creating your first component version.

How It Works

  flowchart LR
    A[component-constructor.yaml] -- ocm add cv --> B[CTF] -- ocm transfer --> C[OCI Repository]

Component versions are created using a component-constructor.yaml file that describes components and their artifacts. The OCM CLI builds these into a Common Transport Format (CTF) archive, which can then be transferred to any OCI registry with ocm transfer.

Prerequisites

Create Your First Component

  1. Set up a working directory

    Create and enter a directory for this tutorial:

    mkdir /tmp/helloworld && cd /tmp/helloworld
  2. Create a local resource file

    Create a simple text file that will become part of your component:

    echo "My first local Resource for an OCM component" > my-local-resource.txt
  3. Define the component

    Create a component-constructor.yaml file that describes your component and its resources:

    # yaml-language-server: $schema=https://ocm.software/schemas/configuration-schema.yaml
    components:
    - name: github.com/acme.org/helloworld # Must at least be a DNS domain as per RFC 1123.
      version: 1.0.0 # Version conforming to SemVer 2.0.
      provider:
        name: acme.org # You must declare a provider, who serves as the owner of the component.
      resources:
        - name: mylocalfile
          type: blob
          input: # Embed by value
            type: file
            path: ./my-local-resource.txt
        - name: image
          type: ociImage
          version: 1.0.0
          access: # Reference externally
            type: ociArtifact
            imageReference: ghcr.io/stefanprodan/podinfo:6.9.1

    Referencing Artifacts

    OCM supports various ways to include resource artifacts in your components via resources.

    Use input to embed content directly, or access to reference external artifacts.

    resource.input (by value)resource.access (by reference)
    StorageContent embedded in Component VersionOnly reference stored
    Use caseLocal files, directories, co-located dataRemote images, charts, resolution at runtime
    TransferContent travels with componentMust be accessible at destination

    For a complete list of supported types, see Input and Access Types.

  4. Build the component version

    Run the OCM CLI to create a CTF archive:

    ocm add cv

    Output:

    component github.com/acme.org/helloworld/1.0.0 constructed ... done!

    This creates a transport-archive directory containing your component version.

    What’s inside the CTF archive?

    The CTF archive is a Content Addressable Storage (CAS) archive that maps descriptors and resources to digests:

    transport-archive/
    ├── artifact-index.json
    └── blobs/
        ├── sha256.096322a7...  # Component config
        ├── sha256.70a2577d...  # Local resource content
        ├── sha256.74db1326...  # Component descriptor
        └── sha256.c8359dfa...  # OCI manifest

    View the artifact index:

    jq . transport-archive/artifact-index.json
    {
      "schemaVersion": 1,
      "artifacts": [
        {
          "repository": "component-descriptors/github.com/acme.org/helloworld",
          "tag": "1.0.0",
          "digest": "sha256:c8359dfaa6353b1b3166449f7ff3a8ef6f1d3a6c6f837cca9cd2ad7e8ef8546e"
        }
      ]
    }

    The content of the transport archive is stored as OCI artifacts. Notice that the repository name of component version artifacts (found at artifacts.respository) are prefixed by component-descriptors/.

    The component version is described as an OCI manifest, including OCM specific annotations.

    jq . transport-archive/blobs/sha256.c8359dfaa6353b1b3166449f7ff3a8ef6f1d3a6c6f837cca9cd2ad7e8ef8546e
    {
      "schemaVersion": 2,
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "artifactType": "application/vnd.ocm.software.component-descriptor.v2",
      "config": {
        "mediaType": "application/vnd.ocm.software/ocm.component.config.v1+json",
        "digest": "sha256:096322a7affa6a26a4549e347399f835b2350454946b4967ffdc570dbed78066",
        "size": 201
      },
      "layers": [
        {
          "mediaType": "application/vnd.ocm.software.component-descriptor.v2+yaml+tar",
          "digest": "sha256:74db132670ec370396ec10160c4e761591d0e9e6c5960c72d2e26c0f9d6f6a76",
          "size": 3072
        },
        {
          "mediaType": "text/plain; charset=utf-8",
          "digest": "sha256:70a2577d7b649574cbbba99a2f2ebdf27904a4abf80c9729923ee67ea8d2d9d8",
          "size": 45,
          "annotations": {
            "software.ocm.artifact": "[{\"identity\":{\"name\":\"mylocalfile\",\"version\":\"1.0.0\"},\"kind\":\"resource\"}]"
          }
        }
      ],
      "annotations": {
        "org.opencontainers.image.authors": "CTF Repository",
        "org.opencontainers.image.description": "\nThis is an OCM OCI Artifact Manifest that contains the component descriptor for the component github.com/acme.org/helloworld.\nIt is used to store the component descriptor in an OCI registry and can be referrenced by the official OCM Binding Library.\n",
        "org.opencontainers.image.documentation": "https://ocm.software",
        "org.opencontainers.image.source": "https://github.com/open-component-model/open-component-model",
        "org.opencontainers.image.title": "OCM Component Descriptor OCI Artifact Manifest for github.com/acme.org/helloworld in version 1.0.0",
        "org.opencontainers.image.url": "https://ocm.software",
        "org.opencontainers.image.version": "1.0.0",
        "software.ocm.componentversion": "component-descriptors/github.com/acme.org/helloworld:1.0.0",
        "software.ocm.creator": "CTF Repository"
      }
    }

    Notice that the output of the component version above contains the component descriptor as one of the layers. It can be identified by its media type, which is application/vnd.ocm.software.component-descriptor.v2+yaml+tar. Since it is saved in tar format, it can be displayed using the following command:

    tar xvf transport-archive/blobs/sha256.74db132670ec370396ec10160c4e761591d0e9e6c5960c72d2e26c0f9d6f6a76 -O

    component-descriptor.yaml

    component:
      componentReferences: null
      name: github.com/acme.org/helloworld
      provider: acme.org
      repositoryContexts: null
      resources:
      - access:
          localReference: sha256:70a2577d7b649574cbbba99a2f2ebdf27904a4abf80c9729923ee67ea8d2d9d8
          mediaType: text/plain; charset=utf-8
          type: localBlob/v1
        digest:
          hashAlgorithm: SHA-256
          normalisationAlgorithm: genericBlobDigest/v1
          value: 70a2577d7b649574cbbba99a2f2ebdf27904a4abf80c9729923ee67ea8d2d9d8
        name: mylocalfile
        relation: local
        type: blob
        version: 1.0.0
      - access:
          imageReference: ghcr.io/stefanprodan/podinfo:6.9.1@sha256:262578cde928d5c9eba3bce079976444f624c13ed0afb741d90d5423877496cb
          type: ociArtifact
        digest:
          hashAlgorithm: SHA-256
          normalisationAlgorithm: genericBlobDigest/v1
          value: 262578cde928d5c9eba3bce079976444f624c13ed0afb741d90d5423877496cb
        name: image
        relation: external
        type: ociImage
        version: 1.0.0
      sources: null
      version: 1.0.0
    meta:
      schemaVersion: v2

    The other elements listed as layers describe the blobs for the local resources stored along with the component version. The digests can be seen in the localReference attributes of the component descriptor.

  5. Verify the result

    List the component version in the archive:

    ocm get cv ./transport-archive//github.com/acme.org/helloworld

    Output:

    COMPONENT                      │ VERSION │ PROVIDER
    ───────────────────────────────┼─────────┼──────────
    github.com/acme.org/helloworld │ 1.0.0   │ acme.org

Explore Repositories

Component versions can be inspected in both local CTF archives and remote OCI registries.

ocm get cv <repository>//<component>:<version>

OCM uses a double-slash (//) notation to separate the repository from the component path:

  • Local CTF: ./transport-archive//github.com/acme.org/helloworld:1.0.0
  • Remote OCI Registry: ghcr.io/open-component-model/ocm//ocm.software/ocmcli:0.17.0

CLI Reference

CommandDescription
ocm add cvCreate component version from constructor file
ocm get cvList and inspect component versions

Next Steps

Sign Component Versions

Add cryptographic signatures for authenticity.

Download Resources

Extract resources from component versions.