Skip to content

<Check>

The <Check> block validates a user’s system state by running shell commands or scripts. It’s used to ensure that users have the right tools installed and their environment is properly configured before proceeding.

<Check
id="check-git"
command="git --version"
title="Check if Git is installed"
description="We need Git for version control"
successMessage="Git is installed!"
failMessage="Git is not installed. Please install it from https://git-scm.com/"
/>

Check blocks and Command blocks share many features in common, however they each have a distinct purpose. Check blocks are focused on reading the state of the world and validating it, while Command blocks are focused on mutating the state of the world to update it to what is needed.

  • id (string) - Unique identifier for this check block
  • title (string) - Display title shown in the UI. Supports inline markdown (bold, italic, links, code).
  • description (string) - Longer description of what’s being checked. Supports inline markdown.
  • command (string) - Inline command to execute (alternative to path)
  • path (string) - Path to a shell script file relative to the runbook (alternative to command)
  • inputsId (string | string[]) - ID of an Inputs block to get template variables from. Can be a single ID or an array of IDs. When multiple IDs are provided, variables are merged in order (later IDs override earlier ones).
  • awsAuthId (string) - ID of an AwsAuth block for AWS credentials. The credentials are passed as environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_REGION). The Check button is disabled until authentication completes.
  • githubAuthId (string) - ID of a GitHubAuth block for GitHub credentials. The credentials are passed as environment variables (GITHUB_TOKEN, GITHUB_USER). The Check button is disabled until authentication completes.
  • successMessage (string) - Message shown when check succeeds (default: “Success”). Supports inline markdown.
  • warnMessage (string) - Message shown on warning (default: “Warning”). Supports inline markdown.
  • failMessage (string) - Message shown when check fails (default: “Failed”). Supports inline markdown.
  • runningMessage (string) - Message shown while running (default: “Checking…”). Supports inline markdown.
  • usePty (boolean) - Whether to use a pseudo-terminal (PTY) for script execution. Defaults to true. Set to false to use pipes instead, which may be needed for scripts that don’t work well with PTY or when simpler output handling is preferred. See PTY Support for details.

Instead of referencing an external <Inputs> block via inputsId, you can nest an <Inputs> component directly inside the Check:

<Check
id="check-s3-bucket"
path="checks/s3-bucket-exists.sh"
title="Verify S3 Bucket Exists"
>
<Inputs id="bucket-config">
```yaml
variables:
- name: BucketName
type: string
description: Name of the S3 bucket to check
validations:
- required
\```
</Inputs>
</Check>

The embedded <Inputs> renders directly within the Check block, allowing users to fill in variables before running the check.

Other blocks can reference this Inputs block using the standard inputsId pattern.

Check blocks run shell scripts to enable users to run some kind of validation.

Scripts can be defined inline using the command prop or stored in external files using the path prop.

When writing scripts for Check blocks:

  • Exit codes matter. Return 0 for success, 1 for failure, or 2 for warning
  • Use logging helpers. Standardized functions like log_info and log_error are available
  • Templatize with variables. Use {{ .inputs.VariableName }} syntax to inject user input

Scripts run in a non-interactive shell environment. See Execution Context for details.

You can write scripts either inline or by referencing script files.

For simple checks, you can define the script directly in the command prop:

<Check
id="check-git"
command="git --version"
title="Check if Git is installed"
successMessage="Git is installed!"
failMessage="Git is not installed."
/>

Inline scripts work best for one-liners or short commands. For anything more complex, use an external script file.

Instead of inline commands, you can reference external shell scripts:

<Check
id="check-aws-auth"
path="checks/aws-authenticated.sh"
title="Verify AWS Authentication"
description="Checking if you're authenticated to AWS"
successMessage="AWS credentials are valid!"
failMessage="AWS authentication failed. Run 'aws configure' to set up credentials."
/>

External scripts are plain old bash scripts. The referenced script checks/aws-authenticated.sh might look like:

#!/bin/bash
log_info "Checking AWS authentication..."
if aws sts get-caller-identity &>/dev/null; then
log_info "AWS credentials are valid"
exit 0
else
log_error "Not authenticated to AWS"
exit 1
fi

The Check block interprets your script’s exit codes as follows:

  • Exit code 0: Success ✓ (green)
  • Exit code 1: Failure ✗ (red)
  • Exit code 2: Warning ⚠ (yellow)

These exit codes will determine how the Runbooks UI renders the result of running a script.

Runbooks provides standardized logging functions for your scripts by automatically importing a logging.sh file that defines a standardized set of Bash logging functions. Using these functions enables consistent output formatting and allows the Runbooks UI to parse log levels for filtering and export.

FunctionOutputDescription
log_info "msg"[timestamp] [INFO] msgGeneral informational messages
log_warn "msg"[timestamp] [WARN] msgWarning conditions
log_error "msg"[timestamp] [ERROR] msgError messages
log_debug "msg"[timestamp] [DEBUG] msgDebug output (only when DEBUG=true)
#!/bin/bash
log_info "Starting validation..."
log_debug "Checking environment variable: $MY_VAR"
if [ -z "$MY_VAR" ]; then
log_warn "MY_VAR is not set, using default"
fi
if ! command -v aws &>/dev/null; then
log_error "AWS CLI is not installed"
exit 1
fi
log_info "Validation complete"

Runbooks automatically injects these logging functions into every bash script at runtime — no source or import is needed. To run these scripts locally outside the Runbooks environment, see the Command block Local Development guide.

There are several ways to collect variables to customize a check’s command or script.

The Check command or script pulls its values from a separate Inputs block.

<Inputs id="region-config">
```yaml
variables:
- name: AwsRegion
type: string
description: AWS region to check
default: us-east-1
\```
</Inputs>
<Check
id="check-region"
command="aws ec2 describe-availability-zones --region {{ .inputs.AwsRegion }}"
inputsId="region-config"
title="Check AWS Region Accessibility"
successMessage="Region {{ .inputs.AwsRegion }} is accessible!"
failMessage="Cannot access region {{ .inputs.AwsRegion }}"
/>

The Check command collects input values directly. These values can be shared with other blocks, just like a standalone Inputs block.

<Check
id="check-kms-key"
path="checks/kms-validation.sh"
title="Validate KMS Key"
>
<Inputs id="inline-kms">
```yaml
variables:
- name: KmsKeyId
type: string
description: KMS Key ID to validate
validations:
- required
\```
</Inputs>
</Check>

You can reference multiple Inputs blocks by passing an array of IDs. Variables are merged in order, with later IDs overriding earlier ones:

<Inputs id="lambda-config" templatePath="templates/lambda" />
<Inputs id="repo-config">
```yaml
variables:
- name: GithubOrgName
type: string
- name: GithubRepoName
type: string
\```
</Inputs>
<Check
id="check-lambda"
path="checks/test-lambda.sh"
inputsId={["lambda-config", "repo-config"]}
title="Test Lambda Function"
/>

In this example, the check has access to all variables from both lambda-config and repo-config. If both define a variable with the same name, the value from repo-config (the later ID) takes precedence.

Scripts run in a persistent environment — environment variable changes (export, unset) and working directory changes (cd) carry forward to subsequent blocks. This lets you structure your runbook like a workflow where earlier steps set up the environment for later steps.

Scripts also run in a non-interactive shell, which means shell aliases (like ll) and shell functions (like nvm, rvm) are not available.

For full details, see Shell Execution Context.

Let’s take a look at some example scripts:

checks/terraform-installed.sh
#!/bin/bash
log_info "Checking for OpenTofu installation..."
if command -v tofu &> /dev/null; then
log_info "OpenTofu is installed: $(tofu version | head -1)"
exit 0
else
log_error "OpenTofu is not installed"
exit 1
fi
checks/disk-space.sh
#!/bin/bash
log_info "Checking available disk space..."
available=$(df -h / | awk 'NR==2 {print $4}' | sed 's/G//')
log_debug "Available space: ${available}GB"
if [ "$available" -lt 1 ]; then
log_error "Less than 1GB available"
exit 1
elif [ "$available" -lt 5 ]; then
log_warn "Less than 5GB available"
exit 2
else
log_info "Disk space OK: ${available}GB available"
exit 0
fi
checks/s3-bucket-exists.sh
#!/bin/bash
BUCKET_NAME="{{ .inputs.BucketName }}"
log_info "Checking if S3 bucket exists..."
log_debug "Bucket name: ${BUCKET_NAME}"
if aws s3 ls "s3://${BUCKET_NAME}" &> /dev/null; then
log_info "Bucket ${BUCKET_NAME} exists"
exit 0
else
log_error "Bucket ${BUCKET_NAME} does not exist"
exit 1
fi

Check blocks can produce outputs that downstream blocks can consume. This enables multi-step workflows where each step builds on the previous one.

Scripts write outputs to a file specified by the $RUNBOOK_OUTPUT environment variable. Each output is a key=value pair on its own line:

#!/bin/bash
# Verify an account and output its ID
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
# Write outputs for downstream blocks
echo "account_id=$ACCOUNT_ID" >> "$RUNBOOK_OUTPUT"
exit 0

Reference outputs from other blocks using the outputs namespace in templates:

Terminal window
# Use the account ID from the verify-account block
echo "Using account {{ .outputs.verify_account.account_id }}"

The full syntax is: {{ .outputs.<block-id>.<output-name> }}

If a block references outputs from another block that hasn’t run yet:

  • The Check button is disabled until the upstream block executes
  • A warning message shows which blocks need to run first
  • The template shows the raw syntax until outputs are available

After a block runs, you can view its outputs by clicking “View Outputs” below the log viewer. Outputs are displayed in a table and can be copied as JSON.

For more details on block outputs, see the Command block documentation.

Scripts can write files to two different destinations, depending on the workflow.

See the Files workspace page for more details.

Use $GENERATED_FILES to capture new files. Any files written to this directory automatically appear in the file panel after the check completes successfully.

#!/bin/bash
# Export current state for review
aws sts get-caller-identity > "$GENERATED_FILES/caller-identity.json"
# Save a diagnostic report
echo "Check ran at $(date)" > "$GENERATED_FILES/diagnostic-report.txt"

You can create subdirectories within $GENERATED_FILES to organize your captured files:

#!/bin/bash
mkdir -p "$GENERATED_FILES/diagnostics"
mkdir -p "$GENERATED_FILES/config"
aws sts get-caller-identity > "$GENERATED_FILES/diagnostics/caller-identity.json"
aws configure list > "$GENERATED_FILES/diagnostics/aws-config.txt"

This creates:

generated/
├── diagnostics/
│ ├── caller-identity.json
│ └── aws-config.txt
└── config/
└── ...
  1. Before your script runs, Runbooks creates a temporary capture directory
  2. The $GENERATED_FILES environment variable points to this directory
  3. Your script writes files to $GENERATED_FILES
  4. After successful execution, files are copied to the generated files directory
  5. The temporary directory is cleaned up

If a <GitClone> block has cloned a repository, the $REPO_FILES environment variable points to the local path of the most recently cloned repository. Scripts can use this to read or validate files inside the cloned repo:

#!/bin/bash
# Validate a config file in the cloned repo
if [ -f "$REPO_FILES/terragrunt.hcl" ]; then
log_info "Found terragrunt.hcl"
exit 0
else
log_error "Missing terragrunt.hcl"
exit 1
fi

Unlike $GENERATED_FILES, writes to $REPO_FILES are not captured to a temporary directory; they happen directly on the filesystem. Changes are visible in the Changed tab via git diff.

The <Check> block works especially well for:

  • Pre-flight checks
  • Validating <Command> blocks
  • Smoke tests that validate a completed Runbook

This might manifest as:

  • Tool Installation Verification: Check if required CLI tools are installed
  • Authentication Validation: Verify users are logged into required services
  • Infrastructure State: Validate that required resources exist
  • Configuration Validation: Ensure config files are properly formatted
  • Network Connectivity: Test connectivity to required services
  • Permissions: Verify users have necessary permissions