Skip to content

Advanced Script Patterns

Joao Palma edited this page Oct 27, 2025 · 3 revisions

Advanced Script Patterns

Skill Level: Advanced

Advanced DotRun script patterns for power users building complex automation solutions.

Configuration-Driven Scripts

Create scripts that adapt behavior based on configuration files:

#!/usr/bin/env bash
### DOC
# Configuration-driven deployment script
# Loads settings from YAML files for different environments
### DOC
set -euo pipefail

source "$DR_CONFIG/helpers/pkg.sh"
validatePkg yq

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

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

  # Export configuration as environment variables
  eval "$(yq eval '.env | to_entries | map("export " + .key + "=" + (.value | tostring)) | .[]' "$config_file")"

  # Load deployment settings
  export APP_NAME=$(yq eval '.app.name' "$config_file")
  export IMAGE_TAG=$(yq eval '.app.image_tag' "$config_file")
  export REPLICAS=$(yq eval '.app.replicas' "$config_file")
}

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

  echo "📋 Loading configuration for $environment..."
  load_config "$environment"

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

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

main "$@"

Multi-Stage Scripts

Scripts that execute different stages based on arguments:

#!/usr/bin/env bash
### DOC
# Multi-stage CI/CD pipeline script
# Supports: build, test, deploy, promote stages
### DOC
set -euo pipefail

run_build() {
  echo "🏗️  Building application..."
  docker build -t "$APP_NAME:$BUILD_TAG" .
  docker push "$REGISTRY/$APP_NAME:$BUILD_TAG"
}

run_tests() {
  echo "🧪 Running test suite..."

  # Unit tests
  echo "🔬 Running unit tests..."
  npm test -- --coverage

  # Integration tests
  echo "🔗 Running integration tests..."
  docker-compose -f test/docker-compose.yml up --abort-on-container-exit

  # Security tests
  echo "🔒 Running security scan..."
  dr security/scan-image "$REGISTRY/$APP_NAME:$BUILD_TAG"
}

run_deploy() {
  local environment="$1"
  echo "🚀 Deploying to $environment..."

  # Deploy using environment-specific configuration
  dr deployment/deploy-with-config "$environment" "$BUILD_TAG"

  # Run health checks
  dr monitoring/health-check "$APP_NAME" "$environment"
}

run_promote() {
  local from_env="$1"
  local to_env="$2"

  echo "⬆️  Promoting from $from_env to $to_env..."

  # Get current image from source environment
  local current_image
  current_image=$(kubectl get deployment "$APP_NAME" -n "$from_env" \
    -o jsonpath='{.spec.template.spec.containers[0].image}')

  # Deploy to target environment
  run_deploy "$to_env"

  echo "✅ Promotion complete: $from_env$to_env"
}

main() {
  local stage="$1"
  export BUILD_TAG="${BUILD_TAG:-$(date +%Y%m%d-%H%M%S)}"
  export APP_NAME="${APP_NAME:-myapp}"
  export REGISTRY="${REGISTRY:-registry.company.com}"

  case "$stage" in
    build)
      run_build
      ;;
    test)
      run_tests
      ;;
    deploy)
      run_deploy "${2:-staging}"
      ;;
    promote)
      run_promote "${2:-staging}" "${3:-production}"
      ;;
    full)
      run_build
      run_tests
      run_deploy "${2:-staging}"
      ;;
    *)
      echo "Usage: dr pipeline <stage> [args...]"
      echo "Stages: build, test, deploy <env>, promote <from> <to>, full [env]"
      exit 1
      ;;
  esac
}

main "$@"

Interactive Scripts with Menus

Create user-friendly interactive scripts:

#!/usr/bin/env bash
### DOC
# Interactive environment management script
# Provides menu-driven interface for common operations
### DOC
set -euo pipefail

show_menu() {
  clear
  echo "🚀 Environment Management"
  echo "========================"
  echo "1) List all environments"
  echo "2) Deploy to staging"
  echo "3) Deploy to production"
  echo "4) Check environment health"
  echo "5) View logs"
  echo "6) Scale application"
  echo "7) Rollback deployment"
  echo "8) Exit"
  echo
}

check_health() {
  echo "Available environments:"
  select env in staging production development; do
    if [[ -n "$env" ]]; then
      dr monitoring/health-check "$APP_NAME" "$env"
      break
    fi
  done
}

scale_application() {
  echo "Select environment:"
  select env in staging production development; do
    if [[ -n "$env" ]]; then
      read -p "Enter number of replicas: " replicas
      if [[ "$replicas" =~ ^[0-9]+$ ]]; then
        kubectl scale deployment/"$APP_NAME" --replicas="$replicas" -n "$env"
        echo "✅ Scaled $APP_NAME to $replicas replicas in $env"
      else
        echo "❌ Invalid number of replicas"
      fi
      break
    fi
  done
}

main() {
  export APP_NAME="${APP_NAME:-myapp}"

  while true; do
    show_menu
    read -p "Select option [1-8]: " choice

    case $choice in
      1)
        kubectl get namespaces | grep -E "(staging|production|development)"
        ;;
      2)
        dr deployment/deploy staging
        ;;
      3)
        echo "⚠️  Deploying to PRODUCTION"
        read -p "Are you sure? [y/N]: " -n 1 -r
        echo
        if [[ $REPLY =~ ^[Yy]$ ]]; then
          dr deployment/deploy production
        fi
        ;;
      4)
        check_health
        ;;
      5)
        echo "Select environment:"
        select env in staging production development; do
          if [[ -n "$env" ]]; then
            kubectl logs -n "$env" deployment/"$APP_NAME" --tail=50
            break
          fi
        done
        ;;
      6)
        scale_application
        ;;
      7)
        echo "Select environment for rollback:"
        select env in staging production; do
          if [[ -n "$env" ]]; then
            dr deployment/rollback "$env"
            break
          fi
        done
        ;;
      8)
        echo "👋 Goodbye!"
        exit 0
        ;;
      *)
        echo "❌ Invalid option: $choice"
        ;;
    esac

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

main "$@"

Dynamic Script Generation

Generate scripts dynamically based on configuration:

#!/usr/bin/env bash
### DOC
# Generate scripts dynamically based on configuration
### DOC
set -euo pipefail

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

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

  local script_content
  script_content=$(
    cat <<'EOF'
#!/usr/bin/env bash
### DOC
# Auto-generated deployment script for {{ENVIRONMENT}}
# Generated on {{TIMESTAMP}}
### DOC
set -euo pipefail

main() {
    echo "🚀 Deploying to {{ENVIRONMENT}}..."
    
    # Load environment-specific configuration
    export APP_NAME="{{APP_NAME}}"
    export IMAGE_TAG="{{IMAGE_TAG}}"
    export REPLICAS={{REPLICAS}}
    export NAMESPACE="{{NAMESPACE}}"
    
    # Execute deployment
    kubectl set image deployment/"$APP_NAME" app="$APP_NAME:$IMAGE_TAG" -n "$NAMESPACE"
    kubectl scale deployment/"$APP_NAME" --replicas="$REPLICAS" -n "$NAMESPACE"
    
    # Wait for rollout
    kubectl rollout status deployment/"$APP_NAME" -n "$NAMESPACE"
    
    echo "✅ Deployment to {{ENVIRONMENT}} completed"
}

main "$@"
EOF
  )

  # Replace placeholders with actual values
  script_content=$(echo "$script_content" | sed "s/{{ENVIRONMENT}}/$environment/g")
  script_content=$(echo "$script_content" | sed "s/{{TIMESTAMP}}/$(date)/g")
  script_content=$(echo "$script_content" | sed "s/{{APP_NAME}}/$(yq eval '.app.name' "$config_file")/g")
  script_content=$(echo "$script_content" | sed "s/{{IMAGE_TAG}}/$(yq eval '.app.image_tag' "$config_file")/g")
  script_content=$(echo "$script_content" | sed "s/{{REPLICAS}}/$(yq eval '.app.replicas' "$config_file")/g")
  script_content=$(echo "$script_content" | sed "s/{{NAMESPACE}}/$(yq eval '.app.namespace' "$config_file")/g")

  # Write generated script
  local script_path="$DR_CONFIG/bin/generated/deploy-$environment.sh"
  mkdir -p "$(dirname "$script_path")"
  echo "$script_content" >"$script_path"
  chmod +x "$script_path"

  echo "✅ Generated deployment script: generated/deploy-$environment"
}

main() {
  local action="$1"

  case "$action" in
    generate-deployment)
      local environment="$2"
      generate_deployment_script "$environment"
      ;;
    generate-all)
      for config_file in config/*.yml; do
        local env_name
        env_name=$(basename "$config_file" .yml)
        generate_deployment_script "$env_name"
      done
      ;;
    *)
      echo "Usage: dr generator <generate-deployment|generate-all> [environment]"
      exit 1
      ;;
  esac
}

main "$@"

Next Steps


These patterns provide the foundation for building sophisticated automation solutions with DotRun.

Clone this wiki locally