logo

Scripts, hooks and runtimes

A build action is one file in one folder. Its name decides when it runs, its extension decides whether Python or Node.js runs it, and anything else in the folder is yours to use as helpers.

Where the scripts go

Repository layout
<repository root>/
  .dsl/
    build_actions/
      pre_build.py        <- runs before the build
      post_build.js       <- runs after the build
      on_end.py           <- runs last, every time
      lib/                <- anything else is yours: helpers, data, package.json

The folder is always .dsl/build_actions/ at the repository root, even when your project lives in a subfolder. Scripts are read from the commit being built: changing a script changes what the next build of the new commit does, and rebuilding an old commit runs that commit's scripts.

How scripts are named

  • A script's file name is the hook name plus .py, .js or .mjs, for example pre_build.py or post_build.mjs.
  • One script per hook. Having both pre_build.py and pre_build.js fails the build.
  • Any other file in the folder is ignored, so keep helper modules there and import them. Python scripts can import from their own folder, and Node scripts can require("./lib/...").
  • If a file name is close to a hook name but misspelled, such as prebuild.py, the build log warns you.

The hooks

Build action hooks in the order they run
Script nameWhen it runsRuns in
pre_checkoutBefore your code is checked outA folder holding only .dsl/build_actions/
post_checkoutRight after checkoutRepository root
pre_buildAfter the engine is ready, before the buildProject folder
post_buildAfter the build, before signing and packagingProject folder
pre_signBefore code signing (only when signing is on)Project folder
post_signAfter code signing (only when signing is on)Project folder
pre_archiveBefore the build output is zipped and uploadedProject folder
post_archiveAfter the zip is uploadedProject folder
on_endAlways last, whether the build succeeded or failedProject folder (or the repository root)
  • A hook runs only if the build gets that far. If pre_build fails, the build stops and the later hooks do not run, except on_end, which always runs.
  • Files written in post_build are shipped. For Godot, Unity and Unreal, anything a post_build script writes into DSL_OUTPUT_DIR is signed (if signing is on), zipped and uploaded with the rest of the build. For CMake, MSBuild, SCons and Xcode, where your artifact settings pick files from the repository by pattern, DSL_OUTPUT_DIR is not set: write the file into the repository where your artifact patterns match, and it ships.
  • on_end does not run when a build is canceled or interrupted by maintenance.

Languages and versions

Script runtimes
LanguageExtensionVersion
Python.py3.14
JavaScript (Node.js).js, .mjsNode 24 LTS

The same versions run on every build machine: Windows, macOS and Linux. Write scripts that work on all three, or branch on DSL_HOST_OS.

There is no shell. To run a command, call it from your script: subprocess.run([...]) in Python, child_process.execFileSync(...) in Node. The runtime's own tools come first on PATH while your script runs, so python, pip, node and npm are the versions above.

Third-party packages

Nothing beyond the standard library is preinstalled. Install what you need from the script itself:

Python
import subprocess, sys, os
subprocess.run([sys.executable, "-m", "pip", "install", "--target", "_deps", "requests"], check=True)
sys.path.insert(0, "_deps")

The Node example runs npm ci in the script's own folder, so commit a package.json and package-lock.json in .dsl/build_actions/ alongside it.

What a script can reach

Scripts run on the build machine with the same access as your engine's own build scripts, such as Unity editor scripts or an Unreal build graph. They are part of your build, so review them like any other code. Every build's record lists which scripts ran and their hashes, so you can tell exactly what produced a build.

Next, What your script is told lists the variables each hook receives.

Something out of date or unclear? Email support@devstreamlabs.com.