Skip to main content

Development environment

The OpsChain Docker-based development environment enables you to list and run individual actions in a manner similar to a running change. After following this guide you should know how to:

  • create a step_context.json file to provide environment variables and properties for your action(s)
  • enter the interactive OpsChain development environment to:
    • list available project resources and actions
    • develop and test your project actions


OpsChain resources and actions can be developed using the OpsChain development environment, accessed via the the opschain dev CLI command.


This guide assumes that you have performed the following steps from the installation guide:

The opschain dev command launches an OpsChain step runner Docker container and must be run from an OpsChain project Git repository. The files in that directory will be made available in the container using a Docker bind mount.

$ cd /path/to/project/git/repository
$ opschain dev
[dev] $ bundle install

The opschain-action commands below assume the OpsChain development environment is being run in the Git repository created as part of the getting started - developer edition. If using a different project, modify these commands to reflect the OpsChain actions available.

Create a step_context.json (optional)

The opschain-action command uses a .opschain/step_context.json file if it exists within the project Git repository working directory. For more information about the step_context.json file, see the step runner reference guide.

$ mkdir -p .opschain
$ cat << EOF > .opschain/step_context.json
"project": {
"properties": $(opschain project show-properties -p web)
"environment": {
"properties": $(opschain environment show-properties -p web -e test)

If your actions rely on OpsChain context values, include the required values in a "context" section in the file. E.g.

"context": {
"project": {
"code": "demo"
"project": {

A sample step_context.json file is available to view here.

Using the OpsChain development environment

The opschain-action command can be used to run OpsChain actions the same way they are run by the step runner. See the OpsChain development environment section of the getting started guide for instructions on how to list and run individual actions.

Unlike when actions are run as part of an OpsChain change, the OpsChain development environment does not persist changes to the project and environment properties to the OpsChain database. Instead, the properties changes are output into the .opschain/step_result.json file. For more information about the step_result.json file, see the step runner reference guide.

Child Steps

Viewing step dependencies

Within the OpsChain development environment (accessed via opschain dev), the opschain-action command can be used to view the expected step tree for an action. Using the OPSCHAIN_DRY_RUN environment variable means the step tree will be output without any of the actions running.


The steps listed may not be accurate during execution because the step information may change dynamically.

[dev] $ OPSCHAIN_DRY_RUN=true opschain-action deploy_in_maintenance_mode

The step_result.json will now contain an expected_step_tree field showing the complete known step tree for the action.

Running child steps

During OpsChain change execution, each child step of an action is executed in its own isolated runner container. As the opschain-action command is being run in the OpsChain development environment, it does not execute an action's child steps. This safeguards the child steps from any issues that may arise from running them in the same container as their parent action. Instead a warning is displayed, detailing the child steps that are not being run.

Automatic execution

To enable opschain-action to run child steps automatically, configure the OPSCHAIN_ACTION_RUN_CHILDREN environment variable:

[dev] $ OPSCHAIN_ACTION_RUN_CHILDREN=true opschain-action deploy_in_maintenance_mode
    • can be set in your shell's configuration, e.g. your .zshrc, to persist the config
    • is only applicable when using opschain-action in the development environment and has no affect on actions running within an OpsChain change
  2. The run_as: :serial/:parallel flags are ignored by opschain-action when running in the development environment. Child steps will always be executed sequentially.
Manual execution

For more granular control of child step execution, actions and their child steps can be listed on the command line directly, and will be executed in the order specified:

[dev] $ opschain-action deploy_in_maintenance_mode enable_maintenance_mode deploy_war disable_maintenance_mode # manually run deploy_in_maintenance_mode and it's children in sequence

Using the OpsChain linter

OpsChain provides a linting tool for detecting issues in project Git repositories. Currently, it only supports detecting Ruby syntax errors. To reduce the likelihood of committing mistakes into your project repository, the linter can be setup as a pre-commit hook in Git. To create the hook, run the following setup command from inside the OpsChain development environment:

[dev] $ opschain-lint --setup

The pre-commit hook will automatically ignore untracked files.

If you would like to commit code that fails linting (e.g. incomplete code) the Git --no-verify argument can be used when committing, e.g. git commit --no-verify.

The hook can be removed permanently by removing the pre-commit hook script:

rm -f .git/hooks/pre-commit

If you would like to suggest a feature for OpsChain's linter please contact us.

Manual linting

The command to invoke the linter manually differs depending on whether you are working inside or outside the OpsChain development environment.

  • outside the OpsChain development environment, the linter can be invoked via the OpsChain CLI opschain dev lint
  • inside the OpsChain development environment, the linter can be invoked via the opschain-lint command

When run manually, the linter tests all not-ignored files in the Git repository. To only lint files tracked by Git set the OPSCHAIN_LINT_GIT_KNOWN_ONLY environment variable, e.g.

[host] $ OPSCHAIN_LINT_GIT_KNOWN_ONLY=true opschain dev lint.

Custom runner images

If your project uses a custom Dockerfile (.opschain/Dockerfile), the OpsChain CLI allows you to use it as the basis for your OpsChain development environment.

Bundler credentials

If your custom Dockerfile uses OpsChain environment variables to supply credentials when running bundler, create a step context JSON file in the .opschain directory that includes the relevant values and this will be used when building your image.

Building and using a custom runner image

To build a Docker image from your project's Dockerfile and then use the image for your OpsChain development environment, execute the following command:

[host] $ opschain dev --build-runner-image --tag my_repository_runner:1.0.0

As part of this process, the CLI will tag the newly built image with the supplied tag.

  1. If the --tag argument is not supplied with the --build-runner-image argument, the newly built image will be assigned the default tag repository_runner:latest.
  2. When the CLI tags the newly built image (with the supplied tag or the default tag) the tag will be removed from any existing image with that tag.

Using a custom runner image

Once built, you can use a custom runner image (without rebuilding it) by supplying the tag to the opschain dev command:

[host] $ opschain dev --tag my_repository_runner:1.0.0

Alternatively, you can use the OPSCHAIN_RUNNER_IMAGE environment variable to specify the tag of the custom runner image. To make the change permanent specify OPSCHAIN_RUNNER_IMAGE in your shell config file, e.g.:

[host] $ echo export OPSCHAIN_RUNNER_IMAGE=\"my_repository_runner:1.0.0\" >> ~/.zshrc # or ~/.bashrc if using bash
[host] $ exec zsh # reload the shell config by starting a new session (replace zsh with bash as appropriate)

Now calls to opschain dev will use the custom image by default.

Enabling tracing

When running OpsChain actions within the OpsChain development environment you can enable tracing by setting the OPSCHAIN_TRACE environment variable.

[dev] $ OPSCHAIN_TRACE=1 opschain-action hello_world

Removing older runner images

The OpsChain development environment container uses the OpsChain step runner image. Upgrading the CLI will cause a new version of the image to be downloaded. To recover the space used by these older images, the docker rmi command can be used to remove them.


The following commands assume you are not using the OPSCHAIN_RUNNER_IMAGE to specify your runner image.

To list the runner images on your machine, execute the following:

export OPSCHAIN_BASE_RUNNER="${OPSCHAIN_BASE_RUNNER:-limepoint/opschain-runner}"
docker images --filter "reference=${OPSCHAIN_BASE_RUNNER}:*"

Take note of the image ids of the older images and remove them as follows:


The image ids below are for example purposes only. Replace them with the image ids of the no longer required runner images (from the filtered "docker images" command above)

docker rmi 62651bfbd35e b05e297066d6

Running commands as root

In some cases, you might want to run commands that require root privileges inside the development environment (e.g. installing a package). However, the opschain user does not have root privileges so there are limitations on what you can do inside the step runner container.

To run commands as root in an OpsChain development environment container, use the docker exec command. First, identify the ID of the container that you wish to run the commands in by using the following command:

docker ps --filter label=opschain-dev

Next, exec into the container as the root user:

docker exec -ti -u 0 <container_id> /bin/bash

Replace <container_id> with the appropriate container ID from the results of the previous command. You now have an interactive Bash shell running as root inside this container and can perform any command you need.

When complete, update your project's Dockerfile to reflect any changes that are required in your project's step runner image.


Use the history command to see the commands you have executed while running as root, making a note of any additional packages or filesystem changes you have made.

What to do next

Try developing your own resources