Skip to content

Migration Guide

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

Migration Guide

Migrating from other tools to DotRun

This guide helps you migrate from existing script management solutions to DotRun while preserving your automation workflows.

From Custom Script Directories

Common Setup

Many developers organize scripts in directories like:

~/scripts/
~/bin/
~/tools/
~/.local/scripts/

Migration Process

1. Assess Your Current Structure

# Analyze your current scripts
find ~/scripts -name "*.sh" -type f | head -20
find ~/bin -name "*.sh" -type f | head -20

# Count scripts by directory
find ~/scripts -name "*.sh" -type f | wc -l

2. Install DotRun

curl -fsSL https://raw.githubusercontent.com/jvPalma/dotrun/master/install.sh | sh

3. Create Migration Script

dr set migration/import-existing-scripts

Add this content:

#!/usr/bin/env bash
### DOC
# Import existing scripts from custom directories
# Preserves structure and adds documentation templates
### DOC
set -euo pipefail

import_scripts_from_directory() {
  local source_dir="$1"
  local category="${2:-imported}"

  if [[ ! -d "$source_dir" ]]; then
    echo "❌ Directory not found: $source_dir"
    return 1
  fi

  echo "📦 Importing scripts from $source_dir..."

  # Find all executable scripts
  while IFS= read -r -d '' script_file; do
    local script_name
    script_name=$(basename "$script_file" .sh)
    local target_name="$category/$script_name"

    echo "Importing: $script_name$target_name"

    # Create target directory
    mkdir -p "$(dirname "$DR_CONFIG/bin/$target_name.sh")"

    # Copy script
    cp "$script_file" "$DR_CONFIG/bin/$target_name.sh"
    chmod +x "$DR_CONFIG/bin/$target_name.sh"

    # Add documentation template if missing
    if ! grep -q "### DOC" "$DR_CONFIG/bin/$target_name.sh"; then
      add_doc_template "$DR_CONFIG/bin/$target_name.sh" "$script_name"
    fi

  done < <(find "$source_dir" -name "*.sh" -type f -executable -print0)
}

add_doc_template() {
  local script_file="$1"
  local script_name="$2"

  # Create backup
  cp "$script_file" "$script_file.bak"

  # Add DOC section after shebang
  {
    head -n 1 "$script_file.bak" # Preserve shebang
    cat <<EOF
### DOC
# $script_name - Imported script
# TODO: Add proper description and usage examples
### DOC
EOF
    tail -n +2 "$script_file.bak" # Rest of the file
  } >"$script_file"

  rm "$script_file.bak"
}

main() {
  echo "🚀 Starting migration to DotRun..."

  # Common script directories
  local common_dirs=(
    "$HOME/scripts"
    "$HOME/bin"
    "$HOME/tools"
    "$HOME/.local/scripts"
    "$HOME/.scripts"
  )

  for dir in "${common_dirs[@]}"; do
    if [[ -d "$dir" ]]; then
      local category
      category=$(basename "$dir")
      import_scripts_from_directory "$dir" "$category"
    fi
  done

  # Custom directories (passed as arguments)
  while [[ $# -gt 0 ]]; do
    local source_dir="$1"
    local category="${2:-$(basename "$source_dir")}"
    import_scripts_from_directory "$source_dir" "$category"
    shift
    [[ $# -gt 0 ]] && shift # Skip category if provided
  done

  echo "✅ Migration complete!"
  echo "📋 Imported scripts:"
  dr -L | grep "imported/"

  echo
  echo "📝 Next steps:"
  echo "1. Review imported scripts: dr -L"
  echo "2. Edit and document scripts: dr set script-name"
  echo "3. Test scripts: dr script-name"
  echo "4. Organize into better categories: dr move old-name new-name"
}

main "$@"

4. Run Migration

# Migrate from common directories
dr migration/import-existing-scripts

# Migrate from custom directory
dr migration/import-existing-scripts ~/my-custom-scripts custom-tools

5. Clean Up and Organize

# Review imported scripts
dr -L | grep imported/

# Reorganize into better categories
dr move imported/deploy-prod deployment/production
dr move imported/backup-db maintenance/database-backup
dr move imported/git-cleanup git/branch-cleanup

# Edit and add proper documentation
dr set deployment/production
dr set maintenance/database-backup

From Make-based Workflows

Common Makefile Patterns

# Typical Makefile tasks
.PHONY: test deploy clean install

test:
	npm test
	pytest

deploy:
	./scripts/deploy.sh staging

clean:
	rm -rf dist/ build/

install:
	npm install
	pip install -r requirements.txt

Migration Strategy

1. Convert Make Targets to Scripts

# Create scripts for each make target
dr set testing/run-all-tests
dr set deployment/staging
dr set maintenance/clean-build
dr set development/install-dependencies

2. Preserve Makefile Integration

# Update Makefile to use DotRun
.PHONY: test deploy clean install

test:
dr testing/run-all-tests

deploy:
dr deployment/staging

clean:
dr maintenance/clean-build

install:
dr development/install-dependencies

3. Migration Script for Make Targets

dr set migration/convert-makefile
#!/usr/bin/env bash
### DOC
# Convert Makefile targets to DotRun scripts
### DOC
set -euo pipefail

extract_make_targets() {
  local makefile="${1:-Makefile}"

  if [[ ! -f "$makefile" ]]; then
    echo "❌ Makefile not found: $makefile"
    exit 1
  fi

  echo "📋 Extracting targets from $makefile..."

  # Extract target names and commands
  awk '
    /^[a-zA-Z][a-zA-Z0-9_-]*:/ {
        target = $1
        gsub(/:/, "", target)
        targets[target] = ""
        current_target = target
        next
    }
    /^\t/ && current_target {
        command = substr($0, 2)  # Remove leading tab
        if (targets[current_target]) {
            targets[current_target] = targets[current_target] "\n" command
        } else {
            targets[current_target] = command
        }
    }
    /^[^ \t]/ && !/^[a-zA-Z][a-zA-Z0-9_-]*:/ {
        current_target = ""
    }
    END {
        for (target in targets) {
            print "TARGET:" target
            print targets[target]
            print "---"
        }
    }
    ' "$makefile"
}

create_script_from_target() {
  local target_name="$1"
  local commands="$2"
  local category="${3:-build}"

  local script_name="$category/$target_name"
  local script_file="$DR_CONFIG/bin/$script_name.sh"

  echo "Creating script: $script_name"

  # Create directory
  mkdir -p "$(dirname "$script_file")"

  # Create script
  cat >"$script_file" <<EOF
#!/usr/bin/env bash
### DOC
# $target_name - Converted from Makefile target
# Original make target: make $target_name
### DOC
set -euo pipefail

main() {
$commands
}

main "\$@"
EOF

  chmod +x "$script_file"
}

main() {
  local makefile="${1:-Makefile}"
  local output
  output=$(extract_make_targets "$makefile")

  # Parse targets and create scripts
  local target_name=""
  local commands=""

  while IFS= read -r line; do
    if [[ "$line" =~ ^TARGET:(.+)$ ]]; then
      # Process previous target if exists
      if [[ -n "$target_name" ]]; then
        create_script_from_target "$target_name" "$commands"
      fi

      # Start new target
      target_name="${BASH_REMATCH[1]}"
      commands=""
    elif [[ "$line" == "---" ]]; then
      # End of target, process it
      if [[ -n "$target_name" ]]; then
        create_script_from_target "$target_name" "$commands"
        target_name=""
        commands=""
      fi
    else
      # Accumulate commands
      if [[ -n "$commands" ]]; then
        commands="$commands"$'\n'"    $line"
      else
        commands="    $line"
      fi
    fi
  done <<<"$output"

  echo "✅ Makefile conversion complete!"
  echo "📋 Created scripts:"
  dr -L | grep build/
}

main "$@"

From Task Runners (npm scripts, etc.)

package.json Scripts

{
  "scripts": {
    "start": "node server.js",
    "test": "jest",
    "build": "webpack --mode=production",
    "deploy": "npm run build && ./deploy.sh",
    "lint": "eslint src/",
    "dev": "nodemon server.js"
  }
}

Migration Script

dr set migration/convert-npm-scripts
#!/usr/bin/env bash
### DOC
# Convert npm scripts to DotRun scripts
### DOC
set -euo pipefail

extract_npm_scripts() {
  if [[ ! -f "package.json" ]]; then
    echo "❌ package.json not found"
    exit 1
  fi

  echo "📋 Extracting npm scripts..."

  # Extract scripts using jq
  if command -v jq >/dev/null; then
    jq -r '.scripts | to_entries[] | "\(.key):\(.value)"' package.json
  else
    # Fallback without jq
    grep -A 100 '"scripts"' package.json \
      | grep -E '^\s*"[^"]*":\s*"[^"]*"' \
      | sed 's/^\s*"\([^"]*\)":\s*"\([^"]*\)".*/\1:\2/'
  fi
}

create_npm_script() {
  local script_name="$1"
  local script_command="$2"
  local category="npm"

  local target_name="$category/$script_name"
  local script_file="$DR_CONFIG/bin/$target_name.sh"

  echo "Creating: $target_name"

  mkdir -p "$(dirname "$script_file")"

  cat >"$script_file" <<EOF
#!/usr/bin/env bash
### DOC
# $script_name - Converted from npm script
# Original command: npm run $script_name
# Executes: $script_command
### DOC
set -euo pipefail

main() {
    # Ensure we're in a Node.js project
    if [[ ! -f "package.json" ]]; then
        echo "❌ package.json not found. Run from project root."
        exit 1
    fi

    echo "🚀 Running: $script_command"
    $script_command
}

main "\$@"
EOF

  chmod +x "$script_file"
}

main() {
  local scripts_output
  scripts_output=$(extract_npm_scripts)

  if [[ -z "$scripts_output" ]]; then
    echo "❌ No npm scripts found"
    exit 1
  fi

  while IFS=: read -r script_name script_command; do
    create_npm_script "$script_name" "$script_command"
  done <<<"$scripts_output"

  echo "✅ npm scripts conversion complete!"
  echo "📋 Created scripts:"
  dr -L | grep npm/

  echo
  echo "💡 You can now run:"
  while IFS=: read -r script_name _; do
    echo "  dr npm/$script_name  (was: npm run $script_name)"
  done <<<"$scripts_output"
}

main "$@"

From Shell Aliases and Functions

Common .bashrc/.zshrc Patterns

# Common aliases
alias ll='ls -la'
alias grep='grep --color=auto'
alias gst='git status'
alias gco='git checkout'
alias gp='git push'

# Common functions
function mkcd() {
  mkdir -p "$1" && cd "$1"
}

function backup() {
  cp "$1" "$1.backup.$(date +%Y%m%d-%H%M%S)"
}

Migration Process

1. Extract Aliases and Functions

dr set migration/convert-shell-aliases
#!/usr/bin/env bash
### DOC
# Convert shell aliases and functions to DotRun scripts
### DOC
set -euo pipefail

extract_aliases() {
  local shell_config="$1"

  echo "📋 Extracting aliases from $shell_config..."

  grep "^alias " "$shell_config" | while IFS= read -r line; do
    # Parse alias name=command
    if [[ "$line" =~ ^alias[[:space:]]+([^=]+)=[[:space:]]*[\'\"]*([^\'\"]+)[\'\"]*$ ]]; then
      local alias_name="${BASH_REMATCH[1]}"
      local alias_command="${BASH_REMATCH[2]}"
      echo "ALIAS:$alias_name:$alias_command"
    fi
  done
}

extract_functions() {
  local shell_config="$1"

  echo "📋 Extracting functions from $shell_config..."

  # Simple function extraction (may need refinement)
  awk '
    /^function [a-zA-Z_][a-zA-Z0-9_]*\(\)/ {
        func_name = $2
        gsub(/\(\)/, "", func_name)
        in_function = 1
        func_body = ""
        next
    }
    /^[a-zA-Z_][a-zA-Z0-9_]*\(\)/ {
        func_name = $1
        gsub(/\(\)/, "", func_name)
        in_function = 1
        func_body = ""
        next
    }
    in_function && /^}/ {
        print "FUNCTION:" func_name ":" func_body
        in_function = 0
        next
    }
    in_function {
        if (func_body) {
            func_body = func_body "\n" $0
        } else {
            func_body = $0
        }
    }
    ' "$shell_config"
}

create_alias_script() {
  local alias_name="$1"
  local alias_command="$2"

  local script_name="aliases/$alias_name"
  local script_file="$DR_CONFIG/bin/$script_name.sh"

  echo "Creating alias script: $script_name"

  mkdir -p "$(dirname "$script_file")"

  cat >"$script_file" <<EOF
#!/usr/bin/env bash
### DOC
# $alias_name - Converted from shell alias
# Original alias: alias $alias_name='$alias_command'
### DOC
set -euo pipefail

main() {
    $alias_command "\$@"
}

main "\$@"
EOF

  chmod +x "$script_file"
}

create_function_script() {
  local func_name="$1"
  local func_body="$2"

  local script_name="functions/$func_name"
  local script_file="$DR_CONFIG/bin/$script_name.sh"

  echo "Creating function script: $script_name"

  mkdir -p "$(dirname "$script_file")"

  cat >"$script_file" <<EOF
#!/usr/bin/env bash
### DOC
# $func_name - Converted from shell function
### DOC
set -euo pipefail

main() {
$func_body
}

main "\$@"
EOF

  chmod +x "$script_file"
}

main() {
  local shell_config="${1:-$HOME/.bashrc}"

  if [[ ! -f "$shell_config" ]]; then
    echo "❌ Shell config not found: $shell_config"
    echo "💡 Try: dr migration/convert-shell-aliases ~/.zshrc"
    exit 1
  fi

  # Extract and convert aliases
  extract_aliases "$shell_config" | while IFS=: read -r type name command; do
    if [[ "$type" == "ALIAS" ]]; then
      create_alias_script "$name" "$command"
    fi
  done

  # Extract and convert functions
  extract_functions "$shell_config" | while IFS=: read -r type name body; do
    if [[ "$type" == "FUNCTION" ]]; then
      create_function_script "$name" "$body"
    fi
  done

  echo "✅ Shell aliases and functions conversion complete!"
  echo "📋 Created scripts:"
  dr -L | grep -E "(aliases/|functions/)"
}

main "$@"

Migration Checklist

Pre-Migration

  • Inventory existing scripts and automation
  • Identify dependencies and requirements
  • Backup existing configurations
  • Plan new organization structure

During Migration

  • Install DotRun
  • Create migration scripts
  • Test converted scripts
  • Add proper documentation
  • Organize into logical categories

Post-Migration

  • Update team documentation
  • Train team members on new workflow
  • Remove old script directories (after verification)
  • Set up collection sharing for teams
  • Establish ongoing maintenance process

Best Practices for Migration

1. Gradual Migration

  • Start with most frequently used scripts
  • Migrate category by category
  • Keep old system running during transition
  • Get team feedback before full migration

2. Documentation

  • Add comprehensive ### DOC sections
  • Include migration notes in documentation
  • Document any behavior changes
  • Create usage examples for complex scripts

3. Testing

  • Test all migrated scripts in clean environment
  • Verify script dependencies
  • Check cross-platform compatibility
  • Validate team collection sharing

4. Organization

  • Use consistent naming conventions
  • Group related scripts logically
  • Consider team workflow patterns
  • Plan for future script additions

Need Help?


Migration to DotRun should improve your automation workflow while preserving the functionality you depend on.

Clone this wiki locally