SWDev Story

SWDev Story: Automation and Scripting

bash, powershell, build automation, common patterns

7.0 Why Automate?

Manual processes are slow, error-prone, and hard to reproduce. Scripts replace manual steps with repeatable, auditable sequences that run identically every time. Good automation:
  • Reduces the chance of forgetting a step in a multi-stage build or deployment.
  • Makes it easy to run the full test suite before committing, not just before a release.
  • Allows CI/CD pipelines (next chapter) to trigger builds automatically on every push.
  • Serves as executable documentation - a build script describes exactly how the project is built.

7.1 Bash

Bash is the default shell on Linux and macOS and is available on Windows through WSL (Windows Subsystem for Linux) and Git Bash. It is the standard language for Unix automation scripts. A minimal Bash build script for a Rust project:
#!/usr/bin/env bash
set -euo pipefail          # exit on error, undefined variable, or pipe failure

echo "=== Building TextFinder ==="
cargo build --release

echo "=== Running tests ==="
cargo test

echo "=== Done ==="
Key Bash constructs:
Bash Language Summary
ConstructExample / Notes
VariablesNAME="TextFinder"; echo "$NAME" - use double quotes around variables.
Command substitutionFILES=$(find . -name "*.rs") - capture command output.
Conditionalsif [ -f "Cargo.toml" ]; then ...; fi
Loopsfor f in *.rs; do echo "$f"; done
Functionsbuild() { cargo build "$@"; }
Exit codescommand || { echo "failed"; exit 1; } - chain with ||.
set -eExit immediately on any non-zero exit code.
set -uTreat undefined variables as errors.
set -o pipefailPropagate failure through pipes.
Heredoccat <<EOF ... EOF - multi-line string literal.

7.2 PowerShell

PowerShell is the standard shell on Windows and is cross-platform (PowerShell 7+ runs on Linux and macOS). Unlike Bash, which passes text through pipes, PowerShell passes objects - the output of one command is a structured object that the next command can filter and transform. A PowerShell build script for the same project:
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

Write-Host "=== Building TextFinder ===" -ForegroundColor Cyan
cargo build --release

Write-Host "=== Running tests ===" -ForegroundColor Cyan
cargo test

Write-Host "=== Done ===" -ForegroundColor Green
Key PowerShell constructs:
PowerShell Language Summary
ConstructExample / Notes
Variables$name = "TextFinder" - always prefixed with $.
CmdletsGet-ChildItem *.rs | Where-Object { $_.Length -gt 0 }
PipelinePasses objects, not text: Get-Process | Sort-Object CPU
Conditionalsif (Test-Path "Cargo.toml") { ... }
Loopsforeach ($f in Get-ChildItem *.rs) { ... }
Functionsfunction Build { param($Config) cargo build --$Config }
Error handling$ErrorActionPreference = 'Stop' - treat errors as exceptions.
Strict modeSet-StrictMode -Version Latest - flag undefined variables.
String interpolation"Building $name in $config mode"
Here-string@" ... "@ - multi-line string literal.

7.3 Common Automation Patterns

Scripts in a development project typically handle these tasks:
  • Build scripts - compile, link, and package the project. Usually wrap the native build tool (cargo, cmake, dotnet, make) with project-specific flags and environment setup.
  • Test scripts - run the test suite, capture exit codes, and fail the build if any test fails. Often include integration tests that require a specific environment.
  • Clean scripts - delete build artifacts so the next build starts from a known state. Important for reproducible builds.
  • Environment setup scripts - install dependencies, set environment variables, or configure paths. Run once when setting up a new developer machine or CI agent.
  • Release scripts - tag the git commit, build release binaries, produce changelogs, and upload artifacts. Sequencing matters; scripts enforce the correct order.
A few principles for maintainable scripts:
  • Fail fast and loudly - use set -e (Bash) or $ErrorActionPreference='Stop' (PowerShell) so errors do not silently continue.
  • Be idempotent where possible - running the script twice should not leave the system in a broken state.
  • Print what you are doing - users and CI logs become readable when each major step is announced.
  • Keep scripts short; move reusable logic into functions or shared helper scripts rather than repeating it.

7.4 References

Scripting References
ResourceDescription
GNU Bash Manual Complete Bash language reference - variables, conditionals, loops, functions, and process control.
PowerShell Docs Microsoft's official PowerShell reference - cmdlets, scripting patterns, and cross-platform usage.
ShellCheck Online Bash linter - paste a script and get immediate feedback on common mistakes.
Google Shell Style Guide Practical conventions for readable, maintainable Bash scripts.