Skip to content
Guidebook

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:

OptionUse it when
The Deltaship GitHub ActionYou use GitHub Actions, on GitHub-hosted or self-hosted runners. A few lines of YAML, nothing to install.
The command-line publisherYou 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#

  1. Create a publish token with Upload drafts only access, under Settings, then Publish tokens. See Publish tokens and CI.
  2. Store it in your CI system as a secret named UDTK_PUBLISH_TOKEN. Never write it in a workflow file or a script.
  3. Note your Studio id (starts with org_) and Game id (starts with gam_) from the Plugin setup card in the dashboard. They are not secret, so a repository variable is fine.
  4. 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: beta

Pin the action to a commit instead of v1 if you want updates only when you choose.

InputRequiredWhat it is
serverYesThe server address from Plugin setup, usually https://api.deltaship.dev.
org and gameYesYour Studio id and Game id.
versionYesThe release version, such as 1.2.0.
build-dirYesThe packaged build folder.
channelNoThe release channel. Defaults to live.
platformNowin64, macos-universal, macos-arm64 or linux-x64. Detected from the folder when there is one obvious answer.
exeNoThe launch file, relative to the build folder, when it cannot be found.
argsNoLaunch arguments for the game, one per line.
direct-uploadNoSend the build straight to your own bucket when Deltaship offers it. Defaults to false. See Direct upload to your bucket.
concurrencyNoParallel uploads, 1 to 16. Defaults to 4.
use-preparedNoReuse a build you already prepared with the command line's prepare, if it still matches.
compare-withNoA 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 BuildCookRun in 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.

CommandWhat it does
prepareMakes a packaged build patch-ready and writes a release file into the build folder.
verifyRe-reads the build and lists changed, missing and added files.
diffCompares two release files and shows what players of the older one would download.
publishPrepares 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 --token option is refused, because command lines end up in logs.
  • The server comes from --server or the UDTK_SERVER variable, and there is no default: CI must say where its token goes. Only https:// addresses are accepted (plain http:// only for localhost).
  • Other options: --platform, --exe, --arg=-windowed for launch arguments (the = form is needed when an argument starts with a dash), --concurrency, --use-prepared and --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.