Script Development Guide - jvPalma/dotrun GitHub Wiki

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.sh โ†’ newName.sh
  • โœ… Documentation renamed: docs/oldName.md โ†’ docs/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.sh โ†’ deployment/deploy.sh
  • โœ… Documentation moved: docs/deployScript.md โ†’ docs/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! ๐Ÿš€

โš ๏ธ **GitHub.com Fallback** โš ๏ธ