Publishing from CI
The GitHub Action and the command-line publisher, with tokens from your CI secrets.
Publish from a build machine without opening the Unreal Editor: package your game, then upload it as a draft release. Works on every plan, with the same publish tokens and the same plan limits as the plugin. Each release waits as a draft until someone publishes it in the dashboard.
There are two ways to do it:
| Option | Use it when |
|---|---|
| The Deltaship GitHub Action | You use GitHub Actions, on GitHub-hosted or self-hosted runners. A few lines of YAML, nothing to install. |
| The command-line publisher | You use another CI system, or a build PC without Unreal. One file that needs only Node 22. |
If your build machine already has Unreal Engine and your project, you can also use the editor's command line; see Publish tokens and CI.
Before you start#
- Create a publish token with Upload drafts only access, under Settings, then Publish tokens. See Publish tokens and CI.
- Store it in your CI system as a secret named
UDTK_PUBLISH_TOKEN. Never write it in a workflow file or a script. - Note your Studio id (starts with
org_) and Game id (starts withgam_) from the Plugin setup card in the dashboard. They are not secret, so a repository variable is fine. - Package your game as usual. The folder you publish is the packaged build, the one that contains the game's executable.
Use the action#
Add a step after your packaging step:
- name: Publish to Deltaship
uses: udtk/actions/publish@v1
env:
UDTK_PUBLISH_TOKEN: ${{ secrets.UDTK_PUBLISH_TOKEN }}
with:
server: https://api.deltaship.dev
org: ${{ vars.UDTK_ORG }}
game: ${{ vars.UDTK_GAME }}
version: 1.2.0
build-dir: Build/Windows
channel: betaPin the action to a commit instead of v1 if you want updates only when you choose.
| Input | Required | What it is |
|---|---|---|
server | Yes | The server address from Plugin setup, usually https://api.deltaship.dev. |
org and game | Yes | Your Studio id and Game id. |
version | Yes | The release version, such as 1.2.0. |
build-dir | Yes | The packaged build folder. |
channel | No | The release channel. Defaults to live. |
platform | No | win64, macos-universal, macos-arm64 or linux-x64. Detected from the folder when there is one obvious answer. |
exe | No | The launch file, relative to the build folder, when it cannot be found. |
args | No | Launch arguments for the game, one per line. |
direct-upload | No | Send the build straight to your own bucket when Deltaship offers it. Defaults to false. See Direct upload to your bucket. |
concurrency | No | Parallel uploads, 1 to 16. Defaults to 4. |
use-prepared | No | Reuse a build you already prepared with the command line's prepare, if it still matches. |
compare-with | No | A release file from an earlier version, to report what its players would download. |
The token is read only from the UDTK_PUBLISH_TOKEN environment variable. A token passed as an input is refused, so it cannot end up in a workflow file.
The action's outputs are release-id, uploaded-bytes, already-stored-bytes, total-bytes, download-bytes (only with compare-with) and exit-code. The job summary shows the release, the build size, what was sent and what Deltaship already had. When something fails, the step fails with a message in plain words; a plan limit message links to the pricing page.
Only the token is hidden in the log, and text that comes back from the server is cleaned before it is shown.
Self-hosted Windows runner with Unreal#
To package and publish in one workflow, use a self-hosted Windows runner that has Unreal Engine installed. Node comes with the runner itself (runner version 2.327 or later).
- Use self-hosted runners only in private repositories, and never for pull requests from forks. A fork's workflow could otherwise run its own code on your machine with your secrets.
- Package with Unreal's
RunUAT.bat BuildCookRunin one step, then publish with the action in the next. A complete example is in the action's README, in the Deltaship repository. - Pass inputs such as the version and channel to the action as inputs, and to scripts through
env:, never by pasting${{ }}into a shell command.
The command-line publisher#
The command-line publisher does what the plugin's offline tools and publisher do, with the same checks, messages and exit codes. It is one file that needs only Node 22 and has nothing to install. Download a version from deltaship.dev (a file named udtk-VERSION.mjs) and check it against the checksum published next to it. In CI, pin the expected checksum in your workflow, so a changed file fails the job instead of running.
| Command | What it does |
|---|---|
prepare | Makes a packaged build patch-ready and writes a release file into the build folder. |
verify | Re-reads the build and lists changed, missing and added files. |
diff | Compares two release files and shows what players of the older one would download. |
publish | Prepares the build (or reuses a verified one), uploads only what Deltaship does not have yet, and creates a draft release. |
Run it with node, followed by the command. A publish looks like this:
node udtk-VERSION.mjs publish Build/Windows --server https://api.deltaship.dev --org org_... --game gam_... --version 1.2.3 --channel beta- The token is read only from
UDTK_PUBLISH_TOKEN. A--tokenoption is refused, because command lines end up in logs. - The server comes from
--serveror theUDTK_SERVERvariable, and there is no default: CI must say where its token goes. Onlyhttps://addresses are accepted (plainhttp://only for localhost). - Other options:
--platform,--exe,--arg=-windowedfor launch arguments (the=form is needed when an argument starts with a dash),--concurrency,--use-preparedand--direct-upload(see below). - It never follows a redirect with your token, and it retries network errors up to four times.
Human-readable progress goes to the error output. Lines beginning UDTK-EVENT carry the same progress as JSON, one per line, for scripts that want to read it.
Direct upload to your bucket#
If your studio has your own storage connected, you can opt in to sending files straight to your bucket: add --direct-upload to the command line, or set direct-upload: true on the action. It is off by default.
- It is used only when Deltaship offers it for that upload, which needs a bucket whose connection test proved it verifies each upload. Otherwise the publisher quietly uploads through Deltaship as usual.
- If the bucket cannot prove the checksum for a file, that file alone goes through Deltaship.
- Your token is never sent to the bucket, redirects are never followed, and the upload addresses, which are signed, are never printed or logged.
- Deltaship checks the stored size and checksum of every file before recording it.
- The Unreal plugin does not upload directly; it always goes through Deltaship.
Exit codes#
The command line, the action and the editor's publisher share the exit codes listed under Publish tokens and CI. Code 5 means a plan limit, 4 a missing or rejected token, 6 that Deltaship refused this release (for example a version that already exists) and 7 that Deltaship could not be reached.
After the upload#
The release is a draft. Check it in the dashboard, then publish it to a channel; see Channels and publishing. With your own bucket connected, new files are stored in it; see Your own storage.