Skip to content

Generic Builder

This page describes creating a generic builder for your Build Goal.

You can construct a Builder around any shell command that can run in whatever environment your SDM runs in. This uses the Node child_process library to spawn another process for each command you supply.

For instance, this documentation site uses a builder that runs these commands:

    "pip install -r requirements.txt",
    "mkdocs build",


To turn a set of operating system commands into a Builder, use thespawnBuilder function in the Build pack. It accepts a SpawnBuilderOptions object, with the following necessary properties:

  • name: a string that helps you identify the builder
  • commands: an array of SpawnCommands to run as child processes.
  • logInterpreter: a function to pull out the interesting bit of the log
  • projectToAppInfo: determine a name and version based on the code.


The commands property contains a list of SpawnCommands to run, sequentially, in a separate process in the project directory.

Create a SpawnCommand object for each command, with a single-word command and the arguments separated:

    command: "pip", 
    argument: ["install", "-r", "requirements.txt"],

You can add options to the SpawnCommand, and they’ll be passed on to the child_process npm package.


The logInterpreter is a function that extracts the interesting bit from the build log. You can customize this function to highlight the particular errors that you see in your own builds, and put exactly what you want to see into chat messages.

A good default is a log interpreter that pulls out the last few lines of the log. There’s a convenience function for that:

lastLinesLogInterpreter("Tail of the log:", 10);

If you provide your own function, make it take a string(the contents of the log) and return an InterpretedLog:

    message: "Here is what you need to know:",
    relevantPart: usefulBitOfLog,


Look at the content of your project and determine the name and version.Here’s one implementation:

async (p: Project) => {
        return {
            id: as RemoteRepoRef,

Put it together

Assemble these properties into a SpawnBuilderObject and get a Builder:

const mkdocsBuilder = spawnBuilder({
    name: "mkdocs spawn builder",
    commands: [
        "pip install -r requirements.txt",
        "mkdocs build",
    ].map(m => asSpawnCommand(m)),

Use the Builder in your BuilderRegistration that you register with a Build Goal.