Git Uploader
Pushes a selected Git resource into an existing Git repository. The commits are
copied unchanged: the commit SHA, authorship, parents and signatures stay the
same, and no commit is created. The resource is published with a Git/v1
access on the target repository, the full ref and the commit, which downloads to
the same digest.
Schema
Fields
| Field | Type | Required | Description |
|---|---|---|---|
match | CEL expression | no | A CEL boolean expression selecting the resources this uploader handles (resource, component and target are available; test access types with resource.access.isType). When omitted, the default below applies. |
repository | CEL expression | yes | URL of the existing target repository in any form a Git/v1 access accepts: a ${…} CEL template or a plain literal. |
ref | CEL expression | yes | Full branch or tag ref the commit is pushed to, e.g. refs/heads/main or refs/tags/v1.0.0: a ${…} CEL template or a plain literal (see Refs). |
repository and ref are evaluated while the transfer graph is built, so a
template that does not evaluate, an invalid repository URL, or a ref that is not
a branch or tag fails the transfer before anything is pushed.
Default match
match: resource.access.isType("Git")The default does not depend on the transfer target: a configured Git uploader pushes Git resources, whether the component version goes to an OCI registry or a CTF archive. A Git resource copied by value becomes a local blob that no longer carries its origin, so it is not selected by default (see Air-gapped transfer).
Origin
The origin of a Git access is the repository path of its source (without
scheme, host and port) and its ref. resource.access.toGit() returns it as a map
with repository and ref:
| Access | toGit().repository | toGit().ref |
|---|---|---|
Git https://github.com/org/repo.git, ref refs/heads/main | org/repo.git | refs/heads/main |
Use it in your own repository template, e.g. to mirror a Git resource below a
different host while keeping its path:
repository: ${"https://git.internal.example/" + resource.access.toGit().repository}
ref: refs/heads/maintoGit() needs a Git access. toGit().ref can be a short name (construction does
not expand it), so set ref to a full branch or tag ref explicitly. Copying a Git
resource as a local blob keeps the archive and the resource digest unchanged and
marks it with the media type application/vnd.ocm.software.git.archive.v1+tar+gzip,
but does not record the origin, so it is pushed with an explicit repository and
ref (see Air-gapped transfer).
Refs
The target ref must be a full branch or tag ref, set explicitly in the uploader
config. A short name such as main does not say whether it is a branch or a tag,
so it fails the transfer and asks for an explicit ref, e.g. ref: refs/heads/main.
HEAD, an empty ref and refs other than branches and tags fail the same way. The
archive and the resource digest do not contain the ref, and signing normalization
excludes the access.
The ref is then pointed at the commit:
- A branch is created, or fast-forwarded when the commit descends from its current tip. A branch that does not fast-forward to the commit fails the transfer.
- A tag is created as a lightweight tag. A tag at another commit fails the transfer.
- A ref that already points at the commit is left unchanged, so repeated transfers succeed.
The full history of the commit is pushed, so the target repository may be empty.
A Git access must be pinned to a commit. The resource digest, if set, is
verified against the archive.
Air-gapped transfer
On the connected side, copy Git resources into a CTF archive with a local blob uploader:
- type: localblob.uploader.transfer.config.ocm.software/v1alpha1The archive keeps its history and is marked with the media type
application/vnd.ocm.software.git.archive.v1+tar+gzip, but it does not carry its
origin. On the air-gapped side, select it explicitly and set repository and
ref:
- type: git.uploader.transfer.config.ocm.software/v1alpha1
match: resource.access.isType("LocalBlob") && has(resource.access.mediaType) && resource.access.mediaType == "application/vnd.ocm.software.git.archive.v1+tar+gzip"
repository: https://git.internal.example/mirror/app.git
ref: refs/heads/mainLocal blobs constructed from a Git input have the media type application/x-tgz;
match them the same way. Local blobs of resources constructed with OCM v1 hold the
files only and are rejected.
Examples
Push one resource to a tag named after the component version:
- type: git.uploader.transfer.config.ocm.software/v1alpha1
match: resource.name == "sources"
repository: https://git.internal.example/mirror/app.git
ref: '${"refs/tags/v" + component.version}'Credentials for the target are resolved for the Git consumer identity of the
target repository URL, as for downloads.