Skip to content

Script Development Guide

Joao Palma edited this page Jan 29, 2026 · 4 revisions

Script Development Guide

Skill Level: Intermediate

This comprehensive guide covers creating, managing, and organizing scripts in DotRun. Learn everything from basic script creation to advanced organization patterns.

📖 Table of Contents


Creating Scripts

Basic Script Creation

The dr set command creates new scripts with proper structure and documentation templates:

# Create a simple script
dr set myscript # Creates myscript.sh in bin/

# Create organized scripts
dr set git/mybranchtool # Creates bin/git/mybranchtool.sh
dr set deploy/staging   # Creates bin/deploy/staging.sh
dr set utils/cleanup    # Creates bin/utils/cleanup.sh

What Happens During Creation

When you create a new script with dr set, DotRun automatically:

  • Creates script file with executable permissions
  • Adds documentation template with ### DOC sections
  • Creates markdown documentation in corresponding docs/ folder
  • Sets up proper shebang and error handling
  • Creates directory structure as needed

Script Template Structure

New scripts are created with this template:

#!/usr/bin/env bash
### DOC
# Brief description of what this script does
# Add usage examples and important notes here
### DOC
set -euo pipefail

# Optional: Import DotRun helpers
source "$DR_CONFIG/helpers/pkg.sh"
source "$DR_CONFIG/helpers/git.sh"

main() {
  echo "🚀 Running myscript..."

  # Your script logic here

  echo "✅ Script completed successfully!"
}

main "$@"

Script Organization

Directory Structure

DotRun encourages organizing scripts by category or function:

~/.config/dotrun/bin/
├── git/                    # Git workflow scripts
│   ├── branch-cleanup.sh
│   ├── smart-commit.sh
│   └── merge-tool.sh
├── deploy/                 # Deployment scripts
│   ├── staging.sh
│   ├── production.sh
│   └── rollback.sh
├── docker/                 # Docker utilities
│   ├── build-image.sh
│   └── cleanup-containers.sh
├── utils/                  # General utilities
│   ├── backup.sh
│   └── system-check.sh
└── project/               # Project management
    ├── setup.sh
    └── clean.sh

Best Organization Patterns

By Technology Stack

dr set react/component-generator
dr set node/api-tester
dr set python/data-processor
dr set go/service-builder

By Workflow Stage

dr set development/setup-env
dr set testing/run-suite
dr set staging/deploy
dr set production/deploy

By Team Function

dr set frontend/build-assets
dr set backend/migrate-db
dr set devops/scale-cluster
dr set qa/run-tests

Moving and Renaming Scripts

DotRun provides powerful commands for reorganizing your scripts while maintaining all documentation and references.

Available Commands

All these commands work identically:

dr move <source> <destination>    # Primary command
dr mv <source> <destination>      # Short alias

Simple Renaming

Change a script's name while keeping it in the same location:

# Rename script in current location
dr move oldName newName
dr mv backupTool enhanced-backup

What happens:

  • ✅ Script file renamed: oldName.shnewName.sh
  • ✅ Documentation renamed: docs/oldName.mddocs/newName.md
  • ✅ Script references updated in documentation
  • ✅ Executable permissions preserved

Moving to Folders

Organize scripts by moving them into category folders:

# Move script to specific category
dr move deployScript deployment/deploy
dr move backupTool utils/backup
dr move testRunner testing/run-suite

# Create nested organization
dr move gitTool git/advanced/branch-manager

What happens:

  • ✅ Script moved: deployScript.shdeployment/deploy.sh
  • ✅ Documentation moved: docs/deployScript.mddocs/deployment/deploy.md
  • ✅ Directory structure created automatically
  • ✅ References updated throughout documentation

Moving Between Folders

Reorganize scripts across different categories:

# Move from one category to another
dr move git/oldTool docker/container-tool
dr move utils/helper backend/api-helper
dr move testing/legacy qa/regression-tests

# Restructure deeply nested scripts
dr move project/frontend/old-build frontend/build-optimized

What happens:

  • ✅ Script moved between directories with full path update
  • ✅ Documentation follows the same path structure
  • ✅ Old directories cleaned up if empty
  • ✅ All internal references updated

Rename and Move Simultaneously

Change both the name and location in one command:

# Rename and relocate
dr move oldScript deployment/new-deploy-tool
dr move helper utils/enhanced-helper
dr move test-runner qa/comprehensive-tester

# Complex reorganization
dr move legacy/old-git-tool git/modern/branch-manager

What happens:

  • ✅ Complete relocation with new name
  • ✅ Documentation structure mirrors script organization
  • ✅ All references and links updated
  • ✅ Maintains complete audit trail

What Gets Updated During Move/Rename

DotRun's move operation is comprehensive and updates:

1. Script Files

  • Script file physically moved/renamed
  • Executable permissions preserved
  • File modification dates maintained

2. Documentation Files

  • Markdown documentation moved to corresponding location
  • Internal documentation references updated
  • Cross-references between docs updated

3. Script Content

  • Script name references in ### DOC sections updated
  • Usage examples updated if they reference the script name
  • Help text and error messages updated

4. Directory Management

  • New directories created as needed
  • Empty directories cleaned up automatically
  • Proper directory permissions set

5. Validation and Safety

  • Prevents overwriting existing scripts
  • Validates source script exists
  • Ensures destination path is valid
  • Provides clear error messages for conflicts

Advanced Move Examples

Bulk Reorganization

# Reorganize related scripts together
dr move docker-build docker/build
dr move docker-run docker/run
dr move docker-clean docker/cleanup

# Migrate legacy scripts to new structure
dr move legacy-deploy deployment/legacy
dr move old-backup backup/legacy
dr move test-old testing/legacy

Project-Specific Organization

# Organize by project phase
dr move setup project/setup
dr move build project/build
dr move deploy project/deploy
dr move cleanup project/cleanup

# Create specialized workflows
dr move generic-test project/testing/unit-tests
dr move integration-test project/testing/integration
dr move e2e-test project/testing/e2e

Team-Based Organization

# Organize by team responsibility
dr move api-deploy backend/deployment
dr move ui-build frontend/build
dr move db-migrate data/migration
dr move monitor-setup devops/monitoring

Documentation System

Inline Documentation

Every script includes ### DOC sections for inline help:

#!/usr/bin/env bash
### DOC
# Git branch cleanup tool with smart merge detection
#
# This script safely removes merged branches after confirming
# they have been integrated into the main branch.
#
# Examples:
#   dr git/branch-cleanup          # Interactive mode
#   dr git/branch-cleanup --auto   # Auto-remove merged branches
#   dr git/branch-cleanup --dry-run # Show what would be removed
#
# Safety features:
# - Never removes current branch
# - Never removes main/master branch
# - Confirms before deletion
# - Detects squash-merged branches
### DOC

Markdown Documentation

Comprehensive documentation lives in corresponding markdown files:

# View documentation
dr help git/branch-cleanup # Shows inline ### DOC sections
dr docs git/branch-cleanup # Shows full markdown documentation

Documentation Templates

When creating scripts, documentation templates include:

# Script Name

Brief description of what the script does.

## Usage

```bash
dr script-name [options] [arguments]
```

Options

  • --option1: Description of option 1
  • --option2: Description of option 2

Examples

# Example 1: Basic usage
dr script-name

# Example 2: With options
dr script-name --option1 value

Dependencies

  • tool1: Description of why it's needed
  • tool2: Optional dependency for enhanced features

Notes

Important information about the script behavior, limitations, or special considerations.


---

## Script Templates

### Basic Script Template

```bash
#!/usr/bin/env bash
### DOC
# Brief description
### DOC
set -euo pipefail

main() {
    echo "🚀 Starting script..."

    # Script logic here

    echo "✅ Script completed!"
}

main "$@"

Advanced Script Template

#!/usr/bin/env bash
### DOC
# Advanced script template with full error handling
# Includes argument parsing, validation, and helper integration
### DOC
set -euo pipefail

# Import DotRun helpers
source "$DR_CONFIG/helpers/pkg.sh"
source "$DR_CONFIG/helpers/git.sh"

# Script configuration
readonly SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}" .sh)"
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Default values
DEFAULT_OPTION="value"

usage() {
  cat <<EOF
Usage: dr $SCRIPT_NAME [OPTIONS] [ARGUMENTS]

Description of what this script does.

OPTIONS:
    -h, --help      Show this help message
    -v, --verbose   Enable verbose output
    --option        Specify option value (default: $DEFAULT_OPTION)

EXAMPLES:
    dr $SCRIPT_NAME
    dr $SCRIPT_NAME --option custom-value
    dr $SCRIPT_NAME --verbose

EOF
}

validate_dependencies() {
  validatePkg git docker
  # Add other dependency checks
}

parse_arguments() {
  local option="$DEFAULT_OPTION"
  local verbose=false

  while [[ $# -gt 0 ]]; do
    case $1 in
      -h | --help)
        usage
        exit 0
        ;;
      -v | --verbose)
        verbose=true
        shift
        ;;
      --option)
        option="$2"
        shift 2
        ;;
      *)
        echo "❌ Unknown option: $1"
        usage
        exit 1
        ;;
    esac
  done

  # Export parsed values for use in main
  export PARSED_OPTION="$option"
  export PARSED_VERBOSE="$verbose"
}

main() {
  # Parse command line arguments
  parse_arguments "$@"

  # Validate dependencies
  validate_dependencies

  # Main script logic
  echo "🚀 Starting $SCRIPT_NAME..."

  if [[ "$PARSED_VERBOSE" == "true" ]]; then
    echo "🔍 Verbose mode enabled"
    echo "📝 Option value: $PARSED_OPTION"
  fi

  # Your script implementation here

  echo "$SCRIPT_NAME completed successfully!"
}

main "$@"

Git Integration Template

#!/usr/bin/env bash
### DOC
# Git workflow script template
### DOC
set -euo pipefail

source "$DR_CONFIG/helpers/git.sh"
source "$DR_CONFIG/helpers/pkg.sh"

validatePkg git

main() {
  # Ensure we're in a git repository
  cd_repo_root

  # Get current branch and default branch
  local current_branch
  current_branch=$(git_current_branch)

  local default_branch
  default_branch=$(git_default_branch)

  echo "🌿 Current branch: $current_branch"
  echo "🏠 Default branch: $default_branch"

  # Your git operations here

  echo "✅ Git operations completed!"
}

main "$@"

Best Practices

Naming Conventions

Script Names

  • Use descriptive, kebab-case names: branch-cleanup, deploy-staging
  • Include action and context: git-merge-tool, docker-build-image
  • Avoid generic names: Use database-backup instead of backup

Organization Names

  • Use clear category names: git/, docker/, deployment/
  • Group by technology or workflow: frontend/, testing/, monitoring/
  • Keep hierarchy shallow: Prefer git/branch-cleanup over git/branch/cleanup

Documentation Standards

Inline Documentation (### DOC)

  • Start with one-line description
  • Include usage examples
  • Document important options and flags
  • Note dependencies and requirements

Markdown Documentation

  • Follow consistent structure (Usage, Options, Examples, Notes)
  • Include practical examples
  • Document edge cases and limitations
  • Keep it updated when script changes

Error Handling

Use Proper Bash Options

set -euo pipefail # Exit on error, undefined vars, pipe failures

Validate Inputs

if [[ -z "$required_param" ]]; then
  echo "❌ Required parameter missing"
  exit 1
fi

Check Dependencies

source "$DR_CONFIG/helpers/pkg.sh"
validatePkg git docker kubectl

Security Considerations

Never Hardcode Secrets

# ❌ Bad
PASSWORD="secret123"

# ✅ Good
PASSWORD="${PASSWORD:-$(read -s -p "Enter password: ")}"

Validate File Paths

# ❌ Bad
rm -rf "$user_input"

# ✅ Good
if [[ "$user_input" =~ ^[a-zA-Z0-9/_-]+$ ]]; then
  rm -rf "$user_input"
else
  echo "❌ Invalid path format"
  exit 1
fi

Advanced Patterns

Multi-Environment Scripts

#!/usr/bin/env bash
### DOC
# Deploy to different environments
### DOC
set -euo pipefail

main() {
  local environment="${1:-staging}"

  case "$environment" in
    development | dev)
      deploy_to_development
      ;;
    staging | stage)
      deploy_to_staging
      ;;
    production | prod)
      deploy_to_production
      ;;
    *)
      echo "❌ Unknown environment: $environment"
      echo "Valid options: development, staging, production"
      exit 1
      ;;
  esac
}

deploy_to_development() {
  echo "🧪 Deploying to development..."
  # Development-specific logic
}

deploy_to_staging() {
  echo "🎭 Deploying to staging..."
  # Staging-specific logic
}

deploy_to_production() {
  echo "🚀 Deploying to production..."
  # Production-specific logic with extra validation
  read -p "Are you sure you want to deploy to production? [y/N]: " -n 1 -r
  echo
  if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "❌ Production deployment cancelled"
    exit 1
  fi
}

main "$@"

Configuration-Driven Scripts

#!/usr/bin/env bash
### DOC
# Configuration-driven deployment script
### DOC
set -euo pipefail

# Load configuration
load_config() {
  local config_file="${1:-config/deploy.yml}"

  if [[ ! -f "$config_file" ]]; then
    echo "❌ Configuration file not found: $config_file"
    exit 1
  fi

  # Parse YAML configuration (simplified)
  export APP_NAME=$(grep "app_name:" "$config_file" | cut -d: -f2 | xargs)
  export IMAGE_TAG=$(grep "image_tag:" "$config_file" | cut -d: -f2 | xargs)
  export REPLICAS=$(grep "replicas:" "$config_file" | cut -d: -f2 | xargs)
}

main() {
  local environment="$1"
  local config_file="config/$environment.yml"

  load_config "$config_file"

  echo "📋 Deploying $APP_NAME:$IMAGE_TAG with $REPLICAS replicas"

  # Use configuration values in deployment
  kubectl set image deployment/"$APP_NAME" app="$APP_NAME:$IMAGE_TAG"
  kubectl scale deployment/"$APP_NAME" --replicas="$REPLICAS"
}

main "$@"

Interactive Scripts

#!/usr/bin/env bash
### DOC
# Interactive script with menu system
### DOC
set -euo pipefail

show_menu() {
  echo "🚀 Deployment Menu"
  echo "=================="
  echo "1) Deploy to staging"
  echo "2) Deploy to production"
  echo "3) Rollback deployment"
  echo "4) Check deployment status"
  echo "5) Exit"
  echo
}

main() {
  while true; do
    show_menu
    read -p "Select option [1-5]: " choice

    case $choice in
      1)
        dr deployment/deploy staging
        ;;
      2)
        dr deployment/deploy production
        ;;
      3)
        dr deployment/rollback
        ;;
      4)
        dr deployment/status
        ;;
      5)
        echo "👋 Goodbye!"
        exit 0
        ;;
      *)
        echo "❌ Invalid option: $choice"
        ;;
    esac

    echo
    read -p "Press Enter to continue..."
    clear
  done
}

main "$@"

Next Steps:


Happy scripting! 🚀

Clone this wiki locally