Documentation › Formatting for the Builder

Formatting for the Builder

How to lay out a plain-text runbook so the Builder can turn it into an interactive runbook. The layout is the one you already use to comment a script: a header, then steps made of a title, a dashed line, comments and the code to paste.

A plain-text runbook is an ordinary script in its shell or language, with structured comments. The comments (the header, sections, steps and their descriptions) are what the Builder reads to lay out the interactive runbook. The code is yours: write it exactly as you would run it, and test it before you build. The Builder does not check that commands work. Only the Settings step has rules for its code, because the Builder turns it into fields (Section 2.8).

Supported:

Header lineValues
Shell:PowerShell, pwsh, Bash, sh, zsh
Language:MySQL

2.1 How the rules are marked

Every Required rule is listed in Section 2.10, and every message the Builder gives is explained in Troubleshooting.

2.2 The plain-text runbook file

Required

Convention

2.3 Header

The first thing in the text.

<#
Title of the runbook
Prepared by: Name, Company
Version: 261007.1
Compatible with: Windows Server 2019 and later, PowerShell 5.1
Shell: PowerShell
#>

Required

Convention

LineEffect
First line insideTitle, shown at the top and in the browser tab
Prepared by:Shown under the title
Version:Shown under the title and in the step list
Compatible with:Shown under the title, on its own line: the systems or versions the runbook was written for
Shell: or Language:What the code is written in. It sets the label on each block of code, the coloring, and the line endings used when copying. PowerShell if neither is given

Every header line other than the title is optional, and they may come in any order. Any other line inside the header is ignored: it is not shown in the interactive runbook and not checked, so a mistyped key such as Prepard by: is silently left out. Check the Builder's summary after building.

The <# and #> markers are used for every shell. They are never pasted anywhere.

Any change to the runbook text, however small, starts the interactive runbook fresh: Done marks and the values operators have typed into Settings are not carried over from the old interactive runbook, whether they were kept in the browser or saved to a progress file.

2.4 Sections

All Convention. Three lines, exactly this shape.

# =================================
# SECTION 1: SETUP (one-time only) #
# =================================
# Comments here are the section's introduction.

2.5 Steps

A blank line, the title, a dashed line, comments, then code.


# E. Title of the step
# --------------------
# Comments explaining the step.
code to paste

Required

Convention

2.6 Comments, then code

All Convention.

2.7 Formatting inside comments

All Convention.

WriteResult
# on its ownNew paragraph
# - itemBullet. Indent the next line to continue it
# 1. itemNumbered list
# text (2 spaces before the text, after the # )The line is shown on its own, indented one level. Every 2 more spaces add a level: 4 spaces is two levels. Bullets, numbered items and their continuation lines are not affected
# Example: ... or # Example Values:Starts a boxed block. The rest of the paragraph is shown as typed, keeping its column alignment
$nameShown as code

Things that spoil the display without stopping the build:

2.8 Settings

The interactive runbook reads the code of the unnumbered step titled Settings and puts a field on that card for each setting. Operators type their values into the fields; the plain-text runbook supplies the starting values.

Rules for the Settings step

Required. A runbook has at most one Settings step: one unnumbered step titled Settings.

Required. Every code line in the Settings step is one setting, written as shown below. It starts in the first column, and nothing follows the value, not even a comment.

Shell or languageLineField
PowerShell, pwsh$name = "text" or $name = 'text'Text box
PowerShell, pwsh$name = $true or $name = $falseCheck box
PowerShell, pwsh$name = 30Number box
Bash, sh, zshname="text", name='text' or name=wordText box
Bash, sh, zshname=true or name=falseCheck box
Bash, sh, zshname=30Number box
MySQLSET @name = 'text'; or SET @name = "text";Text box
MySQLSET @name = TRUE; or SET @name = FALSE;Check box
MySQLSET @name = 30;Number box

Required. These are refused:

Settings are for names, addresses, paths and numbers, never passwords or other secrets (Section 2.9).

Using a setting in later steps

Convention. Use the variable ($working_dir, "$target_dir", @db_name). The shell or database fills in the value the operator set when they ran the Settings step. The interactive runbook shows and copies these lines exactly as written.

Loading a setting again in a later step

Convention. A step that must work in a new terminal window or database session, after the Settings variables are gone, can load the settings it needs. Set the setting to itself, on a line of its own starting in the first column:

Shell or languageLine
PowerShell, pwsh$working_dir = $working_dir
Bash, sh, zshtarget_dir="$target_dir" or target_dir=$target_dir
MySQLSET @db_name = @db_name;

The interactive runbook replaces the right-hand side with the current value of that Settings field, so the operator sees and copies, for example, $working_dir = "D:\Work\Client A". Lines after it can then use the variable as usual:

$working_dir   = $working_dir
$settings_file = Join-Path $working_dir "settings.json"

This is the only change the interactive runbook makes outside the Settings step. The name must be one that is set in the Settings step; a line that sets any other variable to itself is left as written. Do not write a setting's value out again in a later step: it would not follow the field.

Example values

Convention. Show sample values in the Settings comments like this:

# Example Values:
#    $app_dir     = "C:\Temp\Export"
#    $working_dir = "C:\Temp\Export\Client"

The box shows the block exactly as typed, with every space kept, so the indentation and alignment are yours to choose. Only the # that starts each comment line is removed. The box never changes when a field is edited.

2.9 Passwords and other secrets

Keep passwords, keys, tokens and other secrets out of runbooks. The Builder does not check for them: it cannot reliably tell a secret from ordinary text, and trying would get in the way of real work. Keeping them out is up to the author.

2.10 Required rules at a glance

The Builder checks exactly these rules, and no others. Troubleshooting explains each message and its fix.

#RuleSectionBuilder says
R1A .txt file, or an interactive runbook (.html) to upgrade2.2, 3.4This file type is not supported (or: This HTML file is not an interactive runbook)
R2Saved as UTF-8, or UTF-16 with a byte-order mark2.2This file is not saved as UTF-8
R3Text, not binary data2.2This file is not saved as UTF-8 (or: This is not a text file)
R4No </script2.2…would cut the runbook short when it is built
R5No <!--2.2…can stop the interactive runbook from being built correctly
R6Starts with <# alone on line 12.3A runbook must start with its header
R7Header closed with #>2.3The header has no closing #> line
R8First header line is the title2.3…must be the title of the runbook
R9A supported shell or language, and not both2.3The shell must be PowerShell, pwsh, Bash, sh or zsh / The language must be MySQL / …not both
R10At least one step2.5No steps were found
R11Settings step holds only setting lines2.8…may only hold setting lines
R12Each setting set once2.8…is already set on line N
R13No worked-out values2.8The value is a command or an expression
R14No expandable $ or backtick in double quotes2.8…that PowerShell would expand
R15Nothing after the value2.8There is text after the closing quote
R16Closing quote present2.8The closing quote is missing
R17A value is given (PowerShell, pwsh and MySQL)2.8No value is given
R18Each section number used once, and each step letter once within its section2.5There is already a Section N… / There is already a step N-X…
R19At most one Settings step2.8There is already a Settings step…

A complete example

A plain-text runbook that follows this documentation and builds without errors. Save it as archive-app-logs.txt and drop it onto the Builder to see the result.

<#
Archive old application logs on a file server
Prepared by: Jo Admin, Example Co
Version: 261008.1
Compatible with: Windows Server 2019 and later, PowerShell 5.1 and 7
Shell: PowerShell
#>

# Before you start
# ----------------
# This runbook moves application log files older than a set number
# of days from the log folder to the archive folder, on one server.
# It deletes nothing.
#
# Use it when the log drive alert fires, or monthly. Do not use it
# for the database server: use "Archive SQL logs" instead.
#
# You need:
#   - a PowerShell session on the server, run as an administrator
#   - write access to the archive folder
#   - nobody else running this runbook on the same server
#
# Stop and tell the runbook owner if any check in Section 1 does not
# match what the step says you should see.
#
# To undo, use the runbook "Restore archived application logs".

# Settings
# --------
# Example Values:
#    $log_dir       = "D:\Logs\App"
#    $archive_dir   = "E:\Archive\AppLogs"
#    $archive_drive = "E"
#    $keep_days     = 30
#    $min_free_gb   = 50
$log_dir       = "D:\Logs\App"
$archive_dir   = "E:\Archive\AppLogs"
$archive_drive = "E"
$keep_days     = 30
$min_free_gb   = 50


# =====================================
# SECTION 1: CHECK (changes nothing) #
# =====================================
# Every step in this section only reads. It is safe to repeat.

# A. Confirm the server and both folders
# --------------------------------------
# You should see the server's name, then True twice.
#
# Stop here if either line says False.
hostname
Test-Path $log_dir
Test-Path $archive_dir


# B. Count the files to be moved
# ------------------------------
# You should see Count and Sum (MB). Write both down for step 3-B.
#
# If Count is 0, there is nothing to archive. Stop here.
$old = Get-ChildItem $log_dir -File | Where-Object LastWriteTime -lt (Get-Date).AddDays(-$keep_days)
$old | Measure-Object Length -Sum | Select-Object Count, @{ n = 'Sum (MB)'; e = { [math]::Round($_.Sum / 1MB) } }


# C. Check there is room in the archive
# -------------------------------------
# You should see one row for drive $archive_drive.
# Look at the Free (GB) column.
#
# Stop here if Free (GB) is under $min_free_gb.
# Do not start Section 2. Send the number to the
# runbook owner.
Get-PSDrive -Name $archive_drive


# ======================================
# SECTION 2: ARCHIVE (moves files) #
# ======================================
# This section changes the server. Run it only after every step in
# Section 1 looked right.

# A. Load the settings again (new window only)
# --------------------------------------------
# Only needed if you closed the PowerShell window after the
# Settings step. Otherwise, check Done and go on.
$log_dir     = $log_dir
$archive_dir = $archive_dir
$keep_days   = $keep_days


# B. Move the old files to the archive
# ------------------------------------
# Moves each file older than $keep_days days. A file that is
# already in the archive is skipped and listed, so this step is
# safe to run again.
#
# You should see one line per skipped file, or nothing at all.
Get-ChildItem $log_dir -File | Where-Object LastWriteTime -lt (Get-Date).AddDays(-$keep_days) | ForEach-Object {
    if (Test-Path (Join-Path $archive_dir $_.Name)) { "Skipped, already archived: $($_.Name)" }
    else { Move-Item $_.FullName -Destination $archive_dir }
}


# =====================================
# SECTION 3: VERIFY AND RECORD #
# =====================================

# A. Check nothing old is left
# ----------------------------
# You should see Count 0, or only the files listed as skipped in
# step 2-B.
Get-ChildItem $log_dir -File | Where-Object LastWriteTime -lt (Get-Date).AddDays(-$keep_days) | Measure-Object | Select-Object Count


# B. Record the result
# --------------------
# 1. In the ticket, record the Count and Sum (MB) from step 1-B and
#    any files listed as skipped in step 2-B.
# 2. Note the date, the server, and who ran it.

Download Runbook Builder

We'll email you a 6-digit code. By downloading you accept the Builder's license.