BoxLang 🚀 A New JVM Dynamic Language Learn More...

build-template

v2.0.1 CommandBox Modules

build-template

build-template logo

build-template is a CommandBox module for releasing CFML projects. Install the module once on each computer. It adds release commands that can:

  • run TestBox tests;
  • build and check a release zip file; and
  • publish a package to ForgeBox and GitHub.

Each project stores its release settings in one small build.json file. You do not need to copy the build kit into every project. One box update command updates the kit for every project on the computer.

How a release works

A normal release has four main steps:

  1. Add a short description of your changes under [Unreleased] in CHANGELOG.md.
  2. Run box release bump to change the version and date the release notes.
  3. Check the project and run a release practice run.
  4. Run the real release.

The release stops when it finds a problem. For example, it stops for uncommitted changes, missing release notes, failed tests, or a version that was already released.

Before you install

Every computer needs:

Your project settings may also require:

  • GitHub CLI to create GitHub Releases;
  • a ForgeBox account to publish to ForgeBox; and
  • a running test server when runTests is true.

Sign in to each service that you use:

gh auth login
box forgebox login

Install

box install build-template

This command installs the module in CommandBox. The release commands then work in every project. Go to a project's root folder and run:

box release init

The setup command:

  • creates build.json with settings found in the project; and
  • creates CHANGELOG.md when the project does not already have one.

Use --docs to copy the detailed RELEASE.md guide into the project. Use --ci to copy a GitHub Actions workflow to .github/workflows/release.yml. You can safely run the setup command again. It keeps existing files unless you use --force.

Review build.json after setup. Correct any setting that could not be found automatically. Pay special attention to the test runner URL and release branch.

Update

box update build-template --system

This command updates the kit for every project on the computer. A project can require a specific kit version through minimumKitVersion in build.json. Release commands stop and show the update command when the installed kit is too old.

Move a project from version 1.x

Projects that contain the old 1.x build folder continue to work before migration. The kit reads the old build/build.json file and prints a migration notice. Run these commands to migrate the project:

box release migrate --dryRun
box release migrate

The migration moves build/build.json to build.json. It deletes only the files that the 1.x kit added under build/. It keeps all other files in that folder. It also updates the old box run-script entries in box.json to use the new release commands.

Review the result with git diff, and then commit it. Use --removeScripts if you want to delete the old scripts instead of updating them.

Your first release

This example starts at version 1.0.0 and releases version 1.0.1.

1. Write the release notes

Add a clear note under ## [Unreleased] in CHANGELOG.md:

## [Unreleased]

### Fixed

- Fixed the login form validation.

This text becomes the description of the GitHub Release.

2. Change the version

Run this command for a bug fix:

box release bump patch

The command changes the version in box.json from 1.0.0 to 1.0.1. It also moves the notes into a dated 1.0.1 section.

Use a different level for other types of changes:

box release bump minor    # 1.0.0 -> 1.1.0 for a new feature
box release bump major    # 1.0.0 -> 2.0.0 for a breaking change

3. Review and commit the changes

git status
git diff
git add box.json CHANGELOG.md
git diff --staged
git commit -m "Release 1.0.1"

Use your changelog filename in the git add command if it is not CHANGELOG.md. The commit stays on your computer until you send it to the remote repository with git push.

If you use GitKraken or another Git app, follow the same steps in the app. Review box.json and the changelog. Stage only those release files. Review the staged changes, commit them as Release 1.0.1, and push the current branch.

4. Check the project

Start the project's test server when tests are enabled. Then run:

box release check

This command does not change anything. It checks the installed kit, settings, Git repository, changelog, required tools, service logins, and test server. It prints a specific fix for each problem.

5. Practice the release

box release run --dryRun

This practice run performs the checks, tests, and package build. It does not publish, create a tag, or push anything.

6. Publish

box release run

The release command:

  1. checks the project;
  2. updates the local production branch without creating a merge commit;
  3. runs the tests and builds a checked zip file;
  4. publishes to ForgeBox when ForgeBox publishing is enabled; and
  5. creates the Git tag and GitHub Release when GitHub publishing is enabled.

The final zip file and its checksums are stored under .artifacts/.

Commands

Run these commands from any folder inside a project. box release help prints the same list.

Command What it does
box release check Finds problems that would stop a release.
box release run --dryRun Practices a release without publishing.
box release run Builds and publishes the current version.
box release run --existingTag Publishes a tag that Gitflow or GitKraken already created at the checked-out commit. It pushes the tag when origin does not have it.
box release run --skipTests Publishes without running the tests again.
box release bump patch Releases a bug fix that remains compatible with older versions.
box release bump minor Releases a new feature that remains compatible with older versions.
box release bump major Releases a change that is not compatible with older versions.
box release bump preminor beta Starts a prerelease such as 1.1.0-beta.1.
box release package Builds and checks the zip file without publishing.
box release engines Runs the tests on each configured CFML engine.
box release notes Shows the release notes for the current version.
box release github Finishes a release that stopped after publishing.
box release init Creates build.json and CHANGELOG.md for a project.
box release migrate Moves a project away from the copied 1.x build folder.

Run box help release run to see all help for one command.

Common settings

Edit build.json in the project root to control the release commands. The setup command creates this file from settings that it finds in the project. It also adds a full list of files that should not be included in the package.

Choose the production branch

branch is the branch that receives release tags and published versions. This is usually main or master. For Gitflow projects, use the production branch. Do not use develop or a temporary release/* branch. The setup command uses Gitflow's configured production branch when it can find one. Always check the generated value.

{
    "branch": "main"
}

Require a kit version

{
    "minimumKitVersion": "2.0.0"
}

The setup command writes the current kit version. Increase this value when the project starts using a feature from a newer kit version.

Publish to GitHub but not ForgeBox

{
    "publish": {
        "forgebox": false,
        "github": true
    }
}

Build an application instead of a module

An application still gets a versioned zip file. It can also get a GitHub Release.

{
    "projectType": "app",
    "publish": {
        "forgebox": false,
        "github": true
    }
}

Do not run tests during the build

Use this setting when another system, such as CI, runs the tests:

{
    "runTests": false
}

Keep extra files out of the package

excludes is the full list of regular expressions used to match top-level files and folders. The default module list excludes build tools, test tools, downloaded dependencies, server settings, editor files, agent notes, archives, and hidden files. An application uses a smaller list. This smaller list allows possible deployment files such as modules, resources, package manifests, .htaccess, and .well-known.

Edit excludes to replace the default list. Use excludesAdd to add project-specific rules without replacing the defaults. This example excludes the top-level docs folder:

{
    "excludesAdd": [
        "^docs$"
    ]
}

JSON requires two backslashes when a regular expression needs one literal backslash.

Test more than one CFML engine

During release init, the setup command finds server.json and each server-*.json file in the project root. It adds the files to engines in filename order. It does not search nested folders. The displayed engine name comes from app.cfengine, the server's name, or the filename, in that order. Review the list and remove servers that are not part of your compatibility tests.

Each configFile must name a CommandBox server JSON file in the project root:

{
    "engines": [
        {
            "name": "Lucee 5",
            "configFile": "[email protected]"
        },
        {
            "name": "Adobe 2023",
            "configFile": "[email protected]"
        }
    ]
}

Run the configured engine list with:

box release engines

The engines run one at a time. A failure does not stop the remaining engines. The final report lists every result. The command returns an error when one or more engines fail.

Common problems

Message How to fix it
Command "release" cannot be resolved Install the module in this CommandBox with box install build-template.
No box.json file was found Run the command from inside a CommandBox project.
This project requires build-template X or newer Run box update build-template --system.
You have uncommitted changes Commit or stash the changes, and then run the command again.
The test server ... did not answer Start the project's test server. You can also correct testRunner or set runTests to false when tests run somewhere else.
Could not find the GitHub CLI Install gh, open a new terminal, and run gh auth login.
does not have a "## [version]" section Add notes under [Unreleased], and then run box release bump.
Tag v1.2.3 already exists That version was already released. Change the version before trying again.
Tag v1.2.3 points to a different commit on origin The local and remote tags point to different commits. Do not move the published tag. Check the release history or use a new version.
build.json contains invalid JSON Check for missing quotes, extra commas, or backslashes that must be doubled.

Run box release check when you do not know what is wrong. It reports release problems without changing the project.

Develop the build kit

Install the development dependencies and run the tests:

box install
box run-script test

The test runner loads this checkout as the build-template module in its own CommandBox. The tests use the working copy even when another version is installed globally. Unit tests cover version rules, changelog handling, settings, project detection, and migration. Integration tests create temporary projects under the ignored .test-work/ folder. They run the real commands through tests/support/Invoke.cfc and use a local Git remote. The tests never publish to ForgeBox or GitHub.

To test the working copy as an installed module, run box install <path to this checkout>. Then open a new shell. box release help should list the commands. The kit uses its own box release run command to release itself.

Files in commands/release/ contain the small command entry points. Files in models/ contain the release work. Rules that do not need CommandBox are kept in separate model components so they are easier to test.

More information

Changelog

This file lists the important changes to this project.

The format follows Keep a Changelog. Version numbers follow Semantic Versioning.

[Unreleased]

[2.0.1] - 2026-09-13

  • Cleaned up README and code documentation.

[2.0.0] - 2026-09-13

Changed

  • build-template is now a CommandBox module. Install it once on each computer with box install build-template. You no longer need to copy a build folder into each project.
  • Build tasks are now commands in the release namespace. The commands are box release run, release check, release bump <level>, release package, release engines, release init, release notes, release github, and release migrate. Run box release help to list them.
  • Project settings now use build.json in the project root. The kit can still read the old 1.x file at build/build.json. It prints a notice until release migrate moves the file.
  • A project can set minimumKitVersion in build.json. Release commands stop and print the update command when the installed kit is too old.
  • Release commands now find the project from any folder inside it.
  • Use box update build-template --system to update the kit.

Removed

  • Projects no longer need the copied build folder, Update.cfc, build-kit.json, templateVersion, or scripts added to box.json by the installer.
  • release init no longer adds scripts to box.json. release migrate updates old 1.x scripts to use the new commands. Existing box run-script release calls continue to work.

Migration from 1.x

  1. Run box install build-template.
  2. Run box release migrate --dryRun in each project. Then run box release migrate, review the changes, and commit them.
  3. Install the module before the release step in CI. See templates/github-release.yml.

[1.5.0] - 2026-09-13

Added

  • build-kit:update (build/Update.cfc) updates the kit files copied into a project. It can download the latest build-template release or use :source=<folder or zip>. It replaces kit files under build/ but keeps build/build.json. It adds new box.json scripts, records the kit version, and prints changelog entries added since the previous version. Use :version= to choose a release. Use :dryRun=true to list changes without applying them.
  • build/build-kit.json records the kit version and repository. The installer now writes the real kit version to templateVersion instead of always writing 1.0.0.
  • release:check now reports whether the release tag exists on origin.

Changed

  • release:existing-tag now checks origin before publishing. It pushes a local-only tag right before creating the GitHub Release. It stops when origin has the same tag at another commit. Before this change, an unpushed Gitflow tag caused the last release step to fail after the package was already published to ForgeBox.
  • The box.json script list moved to build/lib/PackageScriptService.cfc. The install and update tasks now use the same list.

[1.4.2] - 2028-08-10

Changed

  • bump:beta, bump:alpha, and direct preminor calls now stop before changing an active prerelease to a new target. Use :allowPrereleaseRetarget=true to allow that change.

[1.4.1] - 2028-08-07

  • Updated the logo.

[1.4.0] - 2028-08-07

Added

  • Added TestBox tests for version rules, changelog parsing, project settings, public task APIs, multiple-engine workflows, installation, package builds, and safe release practice runs.

Changed

  • Build task components now use direct names and smaller workflow functions.
  • Developer documentation now uses plain language for people who are new to the project.
  • Version, changelog, and project detection rules now use small internal services under build/lib/.
  • The multiple-engine guide now explains that all configured engines run before the command reports any failures.

[1.3.0] - 2028-08-03

Added

  • Added release:existing-tag. This task publishes a release tag created while finishing a Gitflow release in a tool such as GitKraken.

Changed

  • The Gitflow guide now gives the branch steps in order. Create the release branch first. Change the version and commit on that branch. Then finish the release into production and develop.
  • Git instructions now include the matching review, stage, commit, and push steps for people who use GitKraken or another Git app.
  • The guide now has separate GitKraken instructions for valid, old, and already published tags.

[1.2.0] - 2026-07-31

Added

  • Added a Gitflow release guide for plain Git, pull requests, git-flow, and hotfixes.
  • Added a mode that publishes tags created by Gitflow or tag-based CI jobs.
  • Added release:skip-tests as a clear name for the existing option that skips release tests.

Changed

  • A release practice run can run from a non-production branch and prints a warning. A real release must still run from the configured production branch.
  • Release updates now allow fast-forward changes only. Normal releases now reject tags that already exist locally or on the remote.
  • Setup now uses Gitflow's production branch when it is configured. Git instructions now list separate review, stage, and commit steps for developers who are new to Git.
  • The optional GitHub Actions workflow can publish an existing tag. It requests only the repository content permission needed to create the release.

[1.1.0] - 2026-07-30

Added

  • New projects now get a complete exclusion list in build/build.json. Module packages exclude common ColdBox development files. Applications keep possible deployment files such as modules, .htaccess, and .well-known.
  • Setup now finds server.json and root-level server-*.json files in filename order. It names each engine from app.cfengine, the server name, or the filename.

Changed

  • The included build.json is now marked as a starter file that setup can replace. Setup does not replace an existing unmarked or invalid file unless you use :force=true.

[1.0.0] - 2026-07-29

Added

  • Added the first build kit tasks: Build, Release, Bump, TestEngines, Install, and Doctor. They share one settings file at build/build.json.
  • box run-script release checks the project, updates it from the remote, runs tests, builds the package, publishes to ForgeBox, creates a Git tag, and creates a GitHub Release. It uses the changelog notes and attaches the zip file.
  • release:check reports whether a project is ready to release. It prints a fix for each problem.
  • release:dryrun runs a release practice run without publishing.
  • release:hotfix and :skipTests=true skip the tests and print a warning.
  • test:engines runs the tests on each engine in order. It stops at the first failure and lists the engines that passed before the failure.
  • bump:major, bump:minor, and bump:patch change the version and move [Unreleased] notes into a dated section. Prereleases follow SemVer. For example, bump:patch changes 1.2.0-beta.3 to 1.2.0, not 1.2.1.
  • bump:beta, bump:alpha, and bump:prerelease start or update prereleases. Use :preid for another prerelease label.
  • Install.cfc sets up a project in one command. It reads the test runner from box.json and creates the engine list from root-level server-*.json files.
  • The build checks packages before publishing. It compares the number of staged files with the number of files in the zip and stops when the numbers differ.
  • Packages include the short Git commit hash for the source used to build them.
  • excludesAdd adds entries to the default exclusion list. Excluding one more file requires one new setting.
  • Added an optional GitHub Actions workflow under build/templates/.

$ box install build-template

No collaborators yet.
     
  • {{ getFullDate("2026-09-13T10:19:29Z") }}
  • {{ getFullDate("2026-09-13T15:48:21Z") }}
  • 20
  • 1