Customers · Guides
Deliver to GitHub, GitLab, Plastic SCM or Unity
End a workflow with a commit: each run's files land in your repository, with an optional manifest of what they are.
- Before you start
- A GitHub or GitLab repository or a Plastic SCM Cloud repository, and a personal access token that can write to it.
- A workflow you can edit on the canvas.
- You'll end with
- Every run commits its files to your repository, in a folder of their own.
A delivery step commits a run's files to a repository as the run ends, so your game or pipeline picks them up from version control rather than from a download link. There are four: GitHub, GitLab, Plastic SCM and Unity. Put one at the end of a workflow and connect the step that makes the file to it.
Which node to use#
- GitHub commits to a GitHub repository.
- GitLab commits to a GitLab project, on gitlab.com or on your own GitLab server. Subgroups are allowed.
- Plastic SCM checks in to a repository in Plastic SCM Cloud (Unity Version Control). All the files of one step, and the manifest, land in one changeset. Plastic servers you host yourself are not supported.
- Unity commits to the GitHub repository of a Unity project, under
Assets/, so Unity imports the files when it next opens the project. Meshes arrive as.glb, which the glTFast package imports; textures and audio import as they are.
Each takes one input, asset, and accepts any file a step produces: an image, audio, a mesh, a texture map or set, a rig or a file.
Warning: Plastic SCM delivery is new
It follows Unity's published Plastic SCM server API, but has not yet been run against a live Plastic Cloud organisation. Try it on a test branch first, and tell us if a delivery fails.
Connect your repository#
- Add the delivery node on the canvas, and connect the step whose files you want to it.
- Select the node. The inspector asks you to connect and links to the page where you make a personal access token: on GitHub, a token with the
reposcope; on GitLab, one with theapiscope. Paste it. For your own GitLab server, give its address too; the token is only ever sent to that server. - Choose the repository, the branch and the folder from the lists. The branch must already exist.
Plastic SCM#
Plastic SCM makes personal access tokens from its command line, not from a web page. An organisation admin may first have to allow them:
cm accesstoken allowlist add --users="you@studio.com" my-studio@cloud # an admin, once
cm accesstoken create "Sushibelt delivery" 180d my-studio@cloud
cm accesstoken reveal <id from the line above> my-studio@cloudPaste what reveal prints, give the organisation name (my-studio, without @cloud) and choose the Cloud region your organisation is in. The token is only sent to that region, for that organisation. A token lasts as long as you made it for — 180 days at most unless your server allows longer — so make a new one before it runs out.
The token is saved for the project, encrypted, and never shown to a browser again. Every delivery node in the project's workflows uses it, including in runs you start from the API. Unity delivery uses the GitHub token.
Where the files land#
Each file is committed on its own, to a path built from the node's File path setting. By default every run gets its own folder, so a new run never overwrites the last:
- GitHub, GitLab and Plastic SCM:
outputs/{run}/{nodeId}-{index}{ext} - Unity:
Assets/GeneratedAssets/{run}/{nodeId}-{index}{ext}
| Placeholder | Description |
|---|---|
{run} | The first 8 characters of the run id (jobId). |
{jobId} | The whole run id. |
{nodeId} | The delivery node's id on the canvas. |
{index} | The file's position among this node's files: 0, 1, 2… |
{timestamp} | When the delivery ran, in UTC, with : and . replaced by -. |
{name} | The file's name without its extension. |
{ext} | The file's extension, with its dot: .png. |
{filename} | The whole file name. Put a suffix before the extension with {name}-{run}{ext} instead of after {filename}. |
To keep one file that is always the latest, drop {run} from the path. Each run then replaces the file with a new commit.
On Plastic SCM, folders in the path that do not exist yet are created in the same changeset, and the changeset comment is the Changeset comment setting filled in for the step's first file.
What the step reports#
A delivery step is usually the last step of a workflow, so it appears in the run's output. Its result lists each file it committed:
{
"provider": "github",
"delivered": [
{
"path": "outputs/8b2d6f10/e4f2…-0.png",
"sha": "a94a8fe5…",
"htmlUrl": "https://github.com/acme/assets/blob/main/outputs/8b2d6f10/e4f2…-0.png"
}
]
}GitLab reports "provider": "gitlab" and a link to each file, without a sha. Unity reports as GitHub does. Plastic SCM reports the paths and the one changeset they landed in, without links:
{
"provider": "plastic",
"delivered": [
{ "path": "outputs/8b2d6f10/e4f2…-0.png" }
],
"changeset": 42
}The manifest#
Turn on Write manifest JSON in the node's settings and the delivery also commits a JSON file describing what it delivered: each file's path and kind, and the licence each file was made under. An importer can read it instead of guessing from file names.
It is committed to <first folder of the path>/manifest/{run}/{nodeId}.json — with the default GitHub path, that is outputs/manifest/{run}/{nodeId}.json.
{
"version": 1,
"run": "8b2d6f10",
"jobId": "8b2d6f10-4c3a-4e59-a7d2-91f0c3e8b5a4",
"nodeId": "e4f2…",
"nodeType": "GithubDelivery",
"files": [
{ "path": "outputs/8b2d6f10/e4f2…-0.png", "sha": "a94a8fe5…", "filename": "e4f2…-0.png", "kind": "image" }
],
"upstream": {},
"licences": [
{
"path": "outputs/8b2d6f10/e4f2…-0.png",
"provider_key": "fal_ai",
"model": "flux-schnell",
"licence": "Apache-2.0",
"licence_url": "https://www.apache.org/licenses/LICENSE-2.0",
"commercial_use": "yes",
"terms_url": null,
"stamped_at": "2026-09-29T09:14:02Z"
}
],
"commercialUse": "yes",
"deliveredAt": "2026-09-29T09:14:09Z"
}| Field | Description |
|---|---|
versioninteger | The manifest format. Always 1 today. |
run, jobId, nodeId, nodeTypestring | Which run and which delivery node wrote it. |
files[]array | Each committed file: path, filename, kind (image, mesh, audio or other) and, on GitHub, sha. Plastic SCM gives no sha; the manifest is checked in in the same changeset as the files. |
upstreamobject | What the first connected step records about itself, when it records it: prompt, model, providerKey. Often empty; the licences below name the model for certain. |
licences[]array | For each file made by a model: its path, the model and provider, the licence and commercial_use as they stood when it was made, and an attribution line when the licence asks for credit (the Creative Commons BY family). |
commercialUsestring or null | One verdict for the whole delivery, as strict as its strictest file: yes, provider_terms, unchecked or no. Null when no file carries a licence. |
deliveredAtstring (date-time) | When the delivery ran. |
Settings, when you create the workflow from code#
A delivery step's config takes the same settings as the inspector. The token is not one of them: connect it once in the app, from a delivery node in the same project.
| Setting | Description |
|---|---|
repostring · Required | owner/repo on GitHub and Unity; group/project on GitLab; the repository name on Plastic SCM. |
branchstring · Optional | An existing branch. On Plastic SCM a child branch is written main/art.Default: "main" |
pathstring · Optional | The file path, with placeholders. Defaults as above. |
commitMessagestring · Optional | The commit message, with placeholders. On Plastic SCM, the changeset comment. |
manifestboolean · Optional | Also commit the manifest.Default: false |
hoststring · Optional | GitLab only: the server. Leave it out to use the server your token was saved for. |
Note: a failed delivery fails the run
If the token is missing or cannot write, or the repository or branch does not exist, the delivery step fails with an error that says so. The steps before it finished and stay charged; their files are still in your library.
Licences travel with the files#
Read Use a model's licence in your product before you ship a delivered file.